﻿///////////////////////////////////////////////////////////////////////////////////////////////////////
// Copyright (c) 2023, ООО 1С-Софт
// Все права защищены. Эта программа и сопроводительные материалы предоставляются 
// в соответствии с условиями лицензии Attribution 4.0 International (CC BY 4.0)
// Текст лицензии доступен по ссылке:
// https://creativecommons.org/licenses/by/4.0/legalcode
///////////////////////////////////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////////////
// ПОДСИСТЕМА СЕРВИС КРИПТОГРАФИИ DSS
//
// Содержит базовый функционал для взаимодействия с сервисами КриптоПро DSS по протоколу HTTP-сервисов (REST-API)
// - процедуры аутентификации и авторизации
// - работа с сертификатами
// - выполнение криптографических операций
// - сервисные функции
////////////////////////////////////////////////////////////////////////////////

#Область ПрограммныйИнтерфейс

#Область ДляВызоваИзДругихПодсистем

// Следующие процедуры и функции предназначены для интеграции с 1С-Отчетность

#Область БазовыеФункции

// Шифрует данные для переданного списка сертификатов получателей.
//
// Параметры:
//  ИдентификаторПользователя 	- СправочникСсылка.УчетныеЗаписиDSS 
//                            	- Структура - см. НастройкиПользователяПоУмолчанию()
//  ДанныеДокумента 			- ДвоичныеДанные, Строка - один файл, который необходимо обработать
//					 			см. функцию СервисКриптографииDSSКлиентСервер.ПодготовитьДанныеДокумента().
//  СертификатыПолучателей 		- ДвоичныеДанные, Структура, ФиксированнаяСтруктура, Массив, ФиксированныйМассив - 
//								сертификаты получателей зашифрованного сообщения, см. функцию ПолучитьДвоичныеДанныеСертификатов() 
//  ТипШифрования 				- Строка - тип шифрования, варианты: CMS или XML
//  ПараметрыОперации 			- Структура, ФиксированнаяСтруктура - позволяет указать дополнительные параметры операции. Проверяемые поля:
//    * ПараметрыШифрования	- Структура - содержит дополнительные поля для шифрования, см. документацию по сервису 
//			
// Возвращаемое значение:
//   см. СервисКриптографииDSSКлиентСервер.ОтветСервисаПоУмолчанию
//
Функция Зашифровать(ИдентификаторПользователя, 
					ДанныеДокумента, 
					СертификатыПолучателей, 
					ТипШифрования = "CMS", 
					ПараметрыОперации = Неопределено) Экспорт
	
	НастройкиПользователя	= ПолучитьНастройкиПользователя(ИдентификаторПользователя, ПараметрыОперации);
	СтруктураДокумента		= СервисКриптографииDSSКлиентСервер.ПодготовитьДанныеДокумента(ДанныеДокумента);
	СписокСертификатов		= ПолучитьДвоичныеДанныеСертификатов(СертификатыПолучателей);
	
	ПараметрыЗапроса		= Новый Структура;
	ПараметрыЗапроса.Вставить("Content", СтруктураДокумента.Документ);
	ПараметрыЗапроса.Вставить("Encryption", Новый Структура);
	ПараметрыЗапроса.Encryption.Вставить("Type", ?(ТипШифрования = "XML", 1, 0));
	ПараметрыЗапроса.Encryption.Вставить("Certificates", СписокСертификатов);
	Если ПараметрыОперации = Неопределено Тогда
		ПараметрыЗапроса.Encryption.Вставить("Parameters", Новый Структура);
	ИначеЕсли ПараметрыОперации.Свойство("ПараметрыШифрования") Тогда
		ПараметрыЗапроса.Encryption.Вставить("Parameters", ПараметрыОперации.ПараметрыШифрования);
	КонецЕсли;	
	
	Если СписокСертификатов.Количество() > 0 И СтруктураДокумента.ТипДокумента <> "Неопределенно" Тогда
		АдресПодключения	= НастройкиПользователя.Методы.СервисПодписи + "documents/encrypt";
		РезультатЗапроса	= ПодключитьВыполнитьМетодСервиса(НастройкиПользователя, АдресПодключения, ПараметрыЗапроса, "POST", "json", , ПараметрыОперации);
		Если РезультатЗапроса.Выполнено Тогда
			РезультатЗапроса.Результат = СервисКриптографииDSSСлужебный.ПодготовитьРезультатЗапроса(РезультатЗапроса.Результат, СтруктураДокумента.ТипДокумента);
		КонецЕсли;
		
	Иначе
		РезультатЗапроса = СервисКриптографииDSSКлиентСервер.ОтветСервисаПоУмолчанию(Ложь);
		СервисКриптографииDSSСлужебный.ПолучитьОписаниеОшибки(РезультатЗапроса, "ПараметрыЗашифрования");
	КонецЕсли;
	
	СервисКриптографииDSSСлужебный.ПротоколОшибкиПриВызове(РезультатЗапроса, "Зашифровать", ПараметрыЗапроса, , ПараметрыОперации);
	
	Возврат РезультатЗапроса;
	
КонецФункции

// Получает список идентификаторов сертификатов с помощью которых были зашифрованы данные, для указанной учетной записи сервиса.
// Если документ не содержит подходящих сертификатов, то массив пустой.
//
// Параметры:
//   ИдентификаторПользователя 	- СправочникСсылка.УчетныеЗаписиDSS 
//                             	- Структура - см. НастройкиПользователяПоУмолчанию()
//   ДанныеДокумента 			- ДвоичныеДанные, Строка - один файл, который необходимо обработать,
//								см. функцию СервисКриптографииDSSКлиентСервер.ПодготовитьДанныеДокумента().
//   ТипШифрования 				- Строка - тип шифрования, варианты: CMS или XML
//   ПараметрыОперации 			- Структура, ФиксированнаяСтруктура - позволяет указать дополнительные параметры операции.
//			
// Возвращаемое значение:
//   см. СервисКриптографииDSSКлиентСервер.ОтветСервисаПоУмолчанию
//	
Функция СертификатыРасшифрования(ИдентификаторПользователя, ДанныеДокумента, ТипШифрования = "CMS", ПараметрыОперации = Неопределено) Экспорт
	
	НастройкиПользователя	= ПолучитьНастройкиПользователя(ИдентификаторПользователя, ПараметрыОперации);
	СтруктураДокумента		= СервисКриптографииDSSКлиентСервер.ПодготовитьДанныеДокумента(ДанныеДокумента);
	АдресПодключения 		= НастройкиПользователя.Методы.СервисПодписи + "documents/decrypt/parse";
	
	ПараметрыЗапроса	= Новый Структура;
	ПараметрыЗапроса.Вставить("Content", СтруктураДокумента.Документ);
	ПараметрыЗапроса.Вставить("Decryption", Новый Структура);
	ПараметрыЗапроса.Decryption.Вставить("Type", ?(ТипШифрования = "XML", 1, 0));
	ПараметрыЗапроса.Decryption.Вставить("CertificateId", 0);
	
	РезультатЗапроса	= ПодключитьВыполнитьМетодСервиса(НастройкиПользователя, АдресПодключения, ПараметрыЗапроса, "POST", "json", , ПараметрыОперации);
	
	СервисКриптографииDSSСлужебный.ПротоколОшибкиПриВызове(РезультатЗапроса, "СертификатыШифрования", ПараметрыЗапроса, , ПараметрыОперации);
	
	Возврат РезультатЗапроса;
	
КонецФункции

// Расшифровывает данные с использованием переданного идентификатора сертификата пользователя.
//
// Параметры:
//  ИдентификаторПользователя 	- СправочникСсылка.УчетныеЗаписиDSS 
//                            	- Структура - см. НастройкиПользователяПоУмолчанию()
//  ДанныеДокумента 			- ДвоичныеДанные, Строка - один файл, который необходимо обработать,
//								см. функцию СервисКриптографииDSSКлиентСервер.ПодготовитьДанныеДокумента().
//  ИдентификаторСертификата 	- Число - идентификатор сертификата на сервере DSS
//  ТипШифрования 				- Строка - тип шифрования, допустимые варианты: CMS или XML
//  ПинКод 						- Строка - пин-код для доступа к закрытому ключу сертификата учетной записи
//  ПараметрыОперации 			- Структура, ФиксированнаяСтруктура - позволяет указать дополнительные параметры операции. Проверяемы поля:
//    * Транзакция 			- Булево - признак осуществления операции в рамках подтверждения
//    * ТипРезультата 		- Строка - в каком формате возвращать результат, если использовалась транзакция
//			
// Возвращаемое значение:
//   см. СервисКриптографииDSSКлиентСервер.ОтветСервисаПоУмолчанию
//
Функция Расшифровать(
			ИдентификаторПользователя, 
			ДанныеДокумента, 
			ИдентификаторСертификата, 
			ТипШифрования = "CMS", 
			ПинКод = "", 
			ПараметрыОперации = Неопределено) Экспорт
	
	НастройкиПользователя	= ПолучитьНастройкиПользователя(ИдентификаторПользователя, ПараметрыОперации);
	АдресПодключения 		= НастройкиПользователя.Методы.СервисПодписи + "documents/decrypt";
	
	ЭтоТранзакция		= СвойствоСтруктуры(ПараметрыОперации, "Транзакция", Ложь);
	СтруктураДокумента	= СервисКриптографииDSSКлиентСервер.ПодготовитьДанныеДокумента(ДанныеДокумента);
	ПараметрыЗапроса	= Новый Структура();
	ЗначениеПинКода		= ПолучитьЗначениеПароля(ПинКод, НастройкиПользователя);
	
	Если ЭтоТранзакция Тогда
		ПараметрыЗапроса.Вставить("Decryption", Новый Структура);
		Если ЗначениеЗаполнено(ЗначениеПинКода) Тогда
			ПараметрыЗапроса.Decryption.Вставить("PinCode", ЗначениеПинКода);
		КонецЕсли;
		ТипРезультата = СвойствоСтруктуры(ПараметрыОперации, "ТипРезультата");
	Иначе	
		ПараметрыЗапроса.Вставить("Content", СтруктураДокумента.Документ);
		ПараметрыЗапроса.Вставить("Decryption", Новый Структура);
		ПараметрыЗапроса.Decryption.Вставить("Type", ?(ТипШифрования = "XML", 1, 0));
		ПараметрыЗапроса.Decryption.Вставить("PinCode", ЗначениеПинКода);
		ПараметрыЗапроса.Decryption.Вставить("CertificateId", ИдентификаторСертификата);
		ТипРезультата = СтруктураДокумента.ТипДокумента;
	КонецЕсли;
	
	РезультатЗапроса = ПодключитьВыполнитьМетодСервиса(НастройкиПользователя, АдресПодключения, ПараметрыЗапроса, "POST", "json", , ПараметрыОперации);
	Если РезультатЗапроса.Выполнено Тогда
		РезультатЗапроса.Результат = СервисКриптографииDSSСлужебный.ПодготовитьРезультатЗапроса(РезультатЗапроса.Результат, ТипРезультата);
	КонецЕсли;
	
	СервисКриптографииDSSСлужебный.ПротоколОшибкиПриВызове(РезультатЗапроса, "Расшифровать", ПараметрыЗапроса, , ПараметрыОперации);
	
	Возврат РезультатЗапроса;
	
КонецФункции

// Вычисляет хеш для переданных данных с указанным алгоритмом
// Параметры:
//  ИдентификаторПользователя 	- Структура, СправочникСсылка.УчетныеЗаписиDSS - см. функцию НастройкиПользователяПоУмолчанию()
//  ДанныеДокумента 			- ДвоичныеДанные, Строка - один файл, который необходимо обработать,
//								см. функцию СервисКриптографииDSSКлиентСервер.ПодготовитьДанныеДокумента().
//  АлгоритмХеширования 		- Строка - тип хеширования, варианты:
//									GOST R 34.11-94,
//									GR 34.11-2012 256,
//									GR 34.11-2012 512,
//									SHA-1,
//									SHA-256,
//									SHA-384,
//									SHA-512,
//									MD5.
//  ПараметрыОперации 			- Структура, ФиксированнаяСтруктура - позволяет указать дополнительные параметры операции:
//    * ИнвертироватьПолубайты - Булево - если Истина, предварительно инвертирует байты в полученным результате
//
// Возвращаемое значение:
//   см. СервисКриптографииDSSКлиентСервер.ОтветСервисаПоУмолчанию
//
Функция ХешированиеДанных(ИдентификаторПользователя, 
							ДанныеДокумента, 
							АлгоритмХеширования = "GR 34.11-2012 256", 
							ПараметрыОперации = Неопределено) Экспорт
	
	НастройкиПользователя	= ПолучитьНастройкиПользователя(ИдентификаторПользователя, ПараметрыОперации);
	СтруктураДокумента		= СервисКриптографииDSSКлиентСервер.ПодготовитьДанныеДокумента(ДанныеДокумента, Истина);
	АдресПодключения 		= НастройкиПользователя.Методы.СервисПодписи + "documents/hash";
	ИнвертироватьПолубайты	= СвойствоСтруктуры(ПараметрыОперации, "ИнвертироватьПолубайты", Ложь);
	
	ДанныеЗаголовка			= Новый Структура;
	ЭлементХеширования		= Новый Структура("HashAlgorithm", АлгоритмХеширования);
	ДанныеЗаголовка.Вставить("Hash", Новый Структура("Parameters", ЭлементХеширования));
	
	ПредставлениеЗаголовка	= СервисКриптографииDSSСлужебный.ПодготовитьЗаголовокПотока(ДанныеЗаголовка);
	
	Заголовки				= Новый Соответствие;
	Заголовки.Вставить("CPDSS-OPERATION-PARAMS", ПредставлениеЗаголовка);
	Заголовки.Вставить("Content-Type", "application/octet-stream");
	
	РезультатЗапроса	= ПодключитьВыполнитьМетодСервиса(НастройкиПользователя, АдресПодключения, СтруктураДокумента.Документ, "POST", "octet", Заголовки, ПараметрыОперации);
	Если РезультатЗапроса.Выполнено Тогда
		РезультатЗапроса.Результат = СервисКриптографииDSSСлужебный.ПодготовитьРезультатЗапроса(РезультатЗапроса.Результат, СтруктураДокумента.ТипДокумента);
		Если ИнвертироватьПолубайты Тогда
			РезультатЗапроса.Вставить("Результат", СервисКриптографииDSSASNКлиентСервер.ИнвертироватьПолубайты(РезультатЗапроса.Результат));
		КонецЕсли;	
	КонецЕсли;	
	
	СервисКриптографииDSSСлужебный.ПротоколОшибкиПриВызове(РезультатЗапроса, "ХешированиеДанных", ДанныеЗаголовка, , ПараметрыОперации);
	
	Возврат РезультатЗапроса;
	
КонецФункции	

// Данная функция предназначена для формирования подписи одиночного документа. 
// Поддерживает прямой вызов (в т.ч. поточная) и транзакционную схему.
//
// Параметры:
//  ИдентификаторПользователя 	- СправочникСсылка.УчетныеЗаписиDSS 
//                            	- Структура - см. НастройкиПользователяПоУмолчанию()
//  ДанныеДокумента 			- ДвоичныеДанные, Строка - один файл, который необходимо обработать,
//								см. функцию СервисКриптографииDSSКлиентСервер.ПодготовитьДанныеДокумента().
//  СвойстваПодписи 			- Структура - СервисКриптографииDSSКлиентСервер.ПолучитьСвойствоПодписиГост,
//                  			СервисКриптографииDSSКлиентСервер.ПолучитьСвойствоПодписиCMS,
//                  			СервисКриптографииDSSКлиентСервер.ПолучитьСвойствоПодписиXML,
//                  			СервисКриптографииDSSКлиентСервер.ПолучитьСвойствоПодписиCAdES,
//                  			СервисКриптографииDSSКлиентСервер.ПолучитьСвойствоПодписиPDF,
//                  			СервисКриптографииDSSКлиентСервер.ПолучитьСвойствоПодписиMSOffice.
//  ИдентификаторСертификата 	- Число - идентификатор сертификата на сервере DSS
//  ПинКод 						- Строка - пин-код для доступа к закрытому ключу сертификата учетной записи
//  ПотоковыйРежим 				- Булево - формирование подписи в потоковом режим. Потовый режим возможно использовать 
//								только для отделенной CMS подписи без использования транзакции.
//  ПараметрыОперации 			- Структура, ФиксированнаяСтруктура - позволяет указать дополнительные параметры операции. Проверяемы поля:
//    * Транзакция 			- Булево - признак осуществления операции в рамках подтверждения
//    * ТипРезультат 			- Строка - в каком формате возвращать результат, если использовалась транзакция
//			
// Возвращаемое значение:
//   см. СервисКриптографииDSSКлиентСервер.ОтветСервисаПоУмолчанию
// 
Функция Подписать(ИдентификаторПользователя, 
					ДанныеДокумента, 
					СвойстваПодписи, 
					ИдентификаторСертификата, 
					ПинКод = "", 
					Знач ПотоковыйРежим = Ложь,
					ПараметрыОперации = Неопределено) Экспорт
	
	НастройкиПользователя	= ПолучитьНастройкиПользователя(ИдентификаторПользователя, ПараметрыОперации);
	АдресПодключения 		= НастройкиПользователя.Методы.СервисПодписи + "documents";
	ЭтоТранзакция			= СвойствоСтруктуры(ПараметрыОперации, "Транзакция", Ложь);
	ЗначениеПинКода			= ПолучитьЗначениеПароля(ПинКод, НастройкиПользователя);
	
	ПараметрыЗапроса	= Новый Структура;
	ПараметрыЗапроса.Вставить("Signature", Новый Структура);
	
	Если ЗначениеЗаполнено(ЗначениеПинКода) Тогда
		ПараметрыЗапроса.Signature.Вставить("PinCode", ЗначениеПинКода);
	КонецЕсли;
	
	Если НЕ ЭтоТранзакция Тогда 
		ПараметрыЗапроса.Signature.Вставить("CertificateId", ИдентификаторСертификата);
		ПараметрыПодписи = Новый Структура();
		
		Для каждого СтрокаКлюча Из СвойстваПодписи Цикл
			Если СтрокаКлюча.Ключ = "SignatureType" Тогда
				ПараметрыЗапроса.Signature.Вставить("Type", СтрокаКлюча.Значение);
			ИначеЕсли СтрокаКлюча.Ключ = "DocumentType" ИЛИ СтрокаКлюча.Ключ = "DocumentInfo" Тогда
				Продолжить;
			Иначе
				ЗначениеПараметра = ПроверитьПараметрПодписи(НастройкиПользователя, СтрокаКлюча.Ключ, СтрокаКлюча.Значение);
				ПараметрыПодписи.Вставить(СтрокаКлюча.Ключ, ЗначениеПараметра);
			КонецЕсли;	
		КонецЦикла;
		
		Если ПараметрыПодписи.Количество() > 0 Тогда
			ПараметрыЗапроса.Signature.Вставить("Parameters", ПараметрыПодписи);
		КонецЕсли;	
		
		Если ПотоковыйРежим Тогда
			ПотоковыйРежим = ПараметрыЗапроса.Signature.Type = "CAdES"
				И СвойствоСтруктуры(ПараметрыЗапроса.Signature, "Parameters.IsDetached", "false") = "true";
		КонецЕсли;	
		
		СтруктураДокумента = СервисКриптографииDSSКлиентСервер.ПодготовитьДанныеДокумента(ДанныеДокумента, ПотоковыйРежим);
		Если НЕ ПотоковыйРежим Тогда
			ПараметрыЗапроса.Вставить("Content", СтруктураДокумента.Документ);
		КонецЕсли;
		
		ТипРезультата 	= СтруктураДокумента.ТипДокумента
	Иначе
		ПотоковыйРежим 	= Ложь;
		ТипРезультата 	= СвойствоСтруктуры(ПараметрыОперации, "ТипРезультата");
	КонецЕсли;	
		
	Заголовки = Новый Соответствие;
	
	Если ПотоковыйРежим Тогда
		ПредставлениеЗаголовка	= СервисКриптографииDSSСлужебный.ПодготовитьЗаголовокПотока(ПараметрыЗапроса);
		Заголовки.Вставить("CPDSS-OPERATION-PARAMS", ПредставлениеЗаголовка);
		РезультатЗапроса	= ПодключитьВыполнитьМетодСервиса(НастройкиПользователя, АдресПодключения, СтруктураДокумента.Документ, "POST", "octet", Заголовки, ПараметрыОперации);
	Иначе	
		РезультатЗапроса	= ПодключитьВыполнитьМетодСервиса(НастройкиПользователя, АдресПодключения, ПараметрыЗапроса, "POST", "json", Заголовки, ПараметрыОперации);
	КонецЕсли;	
	
	Если РезультатЗапроса.Выполнено Тогда
		РезультатЗапроса.Результат = СервисКриптографииDSSСлужебный.ПодготовитьРезультатЗапроса(РезультатЗапроса.Результат, ТипРезультата);
	КонецЕсли;	
	
	СервисКриптографииDSSСлужебный.ПротоколОшибкиПриВызове(РезультатЗапроса, "Подписать", ПараметрыЗапроса, , ПараметрыОперации);
	
	Возврат РезультатЗапроса;
	
КонецФункции

// Данная функция предназначена для формирования подписи пакета документа. Возможные режимы: транзакция и прямой вызов
//
// Параметры:
//  ИдентификаторПользователя 	- СправочникСсылка.УчетныеЗаписиDSS 
//                            	- Структура - см. НастройкиПользователяПоУмолчанию()
//  МассивДокументов 			- Массив из см. СервисКриптографииDSSКлиентСервер.ПодготовитьПакетДляПодписи
//  СвойстваПодписи 			- Структура - СервисКриптографииDSSКлиентСервер.ПолучитьСвойствоПодписиГост,
//                  			СервисКриптографииDSSКлиентСервер.ПолучитьСвойствоПодписиCMS,
//                  			СервисКриптографииDSSКлиентСервер.ПолучитьСвойствоПодписиXML,
//                  			СервисКриптографииDSSКлиентСервер.ПолучитьСвойствоПодписиCAdES,
//                  			СервисКриптографииDSSКлиентСервер.ПолучитьСвойствоПодписиPDF,
//                  			СервисКриптографииDSSКлиентСервер.ПолучитьСвойствоПодписиMSOffice.
//  ИдентификаторСертификата 	- Число - идентификатор сертификата на сервере DSS
//  ПинКод 						- Строка - пин-код для доступа к закрытому ключу сертификата учетной записи
//  ПараметрыОперации 			- Структура, ФиксированнаяСтруктура - позволяет указать дополнительные параметры операции. Проверяемы поля:
//    * Транзакция 			- Булево - признак осуществления операции в рамках подтверждения
//    * ТипРезультат 			- Строка - в каком формате возвращать результат, если использовалась транзакция
//			
// Возвращаемое значение:
//   см. СервисКриптографииDSSКлиентСервер.ОтветСервисаПоУмолчанию
// 
Функция ПодписатьПакет(ИдентификаторПользователя,
					МассивДокументов, 
					СвойстваПодписи, 
					ИдентификаторСертификата, 
					ПинКод = "", 
					ПараметрыОперации = Неопределено) Экспорт
	
	НастройкиПользователя	= ПолучитьНастройкиПользователя(ИдентификаторПользователя, ПараметрыОперации);
	АдресПодключения 		= НастройкиПользователя.Методы.СервисПодписи + "documents/packagesignature";
	ЭтоТранзакция			= СвойствоСтруктуры(ПараметрыОперации, "Транзакция", Ложь);
	ЗначениеПинКода			= ПолучитьЗначениеПароля(ПинКод, НастройкиПользователя);
	
	ПараметрыЗапроса = Новый Структура;
	ПараметрыЗапроса.Вставить("Signature", Новый Структура);
	
	Если ЗначениеЗаполнено(ЗначениеПинКода) Тогда
		ПараметрыЗапроса.Signature.Вставить("PinCode", ЗначениеПинКода);
	КонецЕсли;
	
	Если НЕ ЭтоТранзакция Тогда
		ПараметрыЗапроса.Signature.Вставить("CertificateId", ИдентификаторСертификата);
		ПараметрыПодписи 		= Новый Структура();
		ДокументыДляОбработки	= СервисКриптографииDSSКлиентСервер.ПодготовитьПакетДляПодписи(МассивДокументов);
		ТипРезультата			= Новый Массив;
		
		Для каждого СтрокаКлюча Из СвойстваПодписи Цикл
			Если СтрокаКлюча.Ключ = "SignatureType" Тогда
				ПараметрыЗапроса.Signature.Вставить("Type", СтрокаКлюча.Значение);
			ИначеЕсли СтрокаКлюча.Ключ = "DocumentType" ИЛИ СтрокаКлюча.Ключ = "DocumentInfo" Тогда
				Продолжить;
			Иначе
				ЗначениеПараметра = ПроверитьПараметрПодписи(НастройкиПользователя, СтрокаКлюча.Ключ, СтрокаКлюча.Значение);
				ПараметрыПодписи.Вставить(СтрокаКлюча.Ключ, ЗначениеПараметра);
			КонецЕсли;	
		КонецЦикла;
		
		Если ПараметрыПодписи.Количество() > 0 Тогда
			ПараметрыЗапроса.Signature.Вставить("Parameters", ПараметрыПодписи);
		КонецЕсли;	
		
		ПараметрыЗапроса.Вставить("Documents", Новый Массив);
		Для каждого СтрокаМассива Из ДокументыДляОбработки Цикл
			СтруктураДокумента = СервисКриптографииDSSКлиентСервер.ПодготовитьДанныеДокумента(СтрокаМассива.Content);
			НоваяСтрока = Новый Структура;
			НоваяСтрока.Вставить("Content", СтруктураДокумента.Документ);
			НоваяСтрока.Вставить("Name", СтрокаМассива.Name);
			НоваяСтрока.Вставить("OriginalContent", СтрокаМассива.OriginalContent);
			
			ПараметрыЗапроса.Documents.Добавить(НоваяСтрока);
			ТипРезультата.Добавить(СтрокаМассива.ВернутьКак);
		КонецЦикла;
		
	Иначе
		ТипРезультата = СвойствоСтруктуры(ПараметрыОперации, "ТипРезультата", Новый Массив);
	КонецЕсли;
		
	РезультатЗапроса = ПодключитьВыполнитьМетодСервиса(НастройкиПользователя, АдресПодключения, ПараметрыЗапроса, "POST", "json", , ПараметрыОперации);
	
	Если РезультатЗапроса.Выполнено Тогда
		
		КоличествоДокументов = РезультатЗапроса.Результат.Results.Количество();
		Если ТипРезультата.Количество() <> КоличествоДокументов Тогда
			ТипРезультата = Новый Массив(КоличествоДокументов);
		КонецЕсли;
		
		Результат = Новый Массив;
		
		Для Счетчик = 0 По КоличествоДокументов - 1 Цикл
			ТекущийЭлемент 	= ТипРезультата[Счетчик];
			Подписанный		= СервисКриптографииDSSСлужебный.ПодготовитьРезультатЗапроса(РезультатЗапроса.Результат.Results[Счетчик], ТекущийЭлемент);
			Результат.Добавить(Подписанный);
		КонецЦикла;

		РезультатЗапроса.Вставить("Результат", Результат);
	КонецЕсли;	
	
	СервисКриптографииDSSСлужебный.ПротоколОшибкиПриВызове(РезультатЗапроса, "ПодписатьПакет", ПараметрыЗапроса, , ПараметрыОперации);
	
	Возврат РезультатЗапроса;
	
КонецФункции

// Добавляет в данные электронной подписи информации о метке времени.
// Имеет смысл для типов подписей, содержащей метку времени: XLT1 и T
//
// Параметры:
//  ИдентификаторПользователя 	- СправочникСсылка.УчетныеЗаписиDSS 
//                            	- Структура - см. НастройкиПользователяПоУмолчанию()
//  ДанныеПодписи	 			- ДвоичныеДанные, Строка - один файл, который необходимо обработать,
//								см. функцию СервисКриптографииDSSКлиентСервер.ПодготовитьДанныеДокумента().
//  СвойстваПодписи 			- Структура - СервисКриптографииDSSКлиентСервер.ПолучитьСвойствоПодписиCAdES
//  ПараметрыОперации 			- Структура, ФиксированнаяСтруктура - позволяет указать дополнительные параметры операции.
//			
// Возвращаемое значение:
//   см. СервисКриптографииDSSКлиентСервер.ОтветСервисаПоУмолчанию
// 
Функция УсовершенствоватьПодпись(ИдентификаторПользователя, ДанныеПодписи, СвойстваПодписи, ПараметрыОперации = Неопределено) Экспорт
	
	НастройкиПользователя	= ПолучитьНастройкиПользователя(ИдентификаторПользователя, ПараметрыОперации);
	АдресПодключения 		= НастройкиПользователя.Методы.СервисПодписи + "documents/enhancesignature";
	
	ПараметрыЗапроса	= Новый Структура;
	ПараметрыЗапроса.Вставить("Signature", Новый Структура);

	ПараметрыПодписи = Новый Структура();
		
	Для каждого СтрокаКлюча Из СвойстваПодписи Цикл
		ИмяКлюча = СтрокаКлюча.Ключ;
		Если ИмяКлюча = "SignatureType" Тогда
			ПараметрыЗапроса.Signature.Вставить("Type", СтрокаКлюча.Значение);
		ИначеЕсли ИмяКлюча = "CADESType" ИЛИ ИмяКлюча = "TSPAddress" Тогда
			ЗначениеПараметра = ПроверитьПараметрПодписи(НастройкиПользователя, СтрокаКлюча.Ключ, СтрокаКлюча.Значение);
			ПараметрыПодписи.Вставить(СтрокаКлюча.Ключ, ЗначениеПараметра);
		КонецЕсли;	
	КонецЦикла;
		
	Если ПараметрыПодписи.Количество() > 0 Тогда
		ПараметрыЗапроса.Signature.Вставить("Parameters", ПараметрыПодписи);
	КонецЕсли;	
		
	СтруктураДокумента = СервисКриптографииDSSКлиентСервер.ПодготовитьДанныеДокумента(ДанныеПодписи);
	ПараметрыЗапроса.Вставить("Content", СтруктураДокумента.Документ);
		
	Заголовки = Новый Соответствие;
	РезультатЗапроса= ПодключитьВыполнитьМетодСервиса(НастройкиПользователя, АдресПодключения, ПараметрыЗапроса, "POST", "json", Заголовки, ПараметрыОперации);
	
	Если РезультатЗапроса.Выполнено Тогда
		РезультатЗапроса.Результат = СервисКриптографииDSSСлужебный.ПодготовитьРезультатЗапроса(РезультатЗапроса.Результат, СтруктураДокумента.ТипДокумента);
	КонецЕсли;	
	
	СервисКриптографииDSSСлужебный.ПротоколОшибкиПриВызове(РезультатЗапроса, "УсовершенствоватьПодпись", ПараметрыЗапроса, , ПараметрыОперации);
	
	Возврат РезультатЗапроса;
	
КонецФункции

// Проверяет сертификат с помощью сервиса КриптоПро SVS
//
// Параметры:
//  ИдентификаторПользователя 	- Структура, СправочникСсылка.УчетныеЗаписиDSS - см. функцию НастройкиПользователяПоУмолчанию()
//  ДанныеСертификата 			- ДвоичныеДанные, Строка - один файл, который необходимо обработать,
//								см. функцию СервисКриптографииDSSКлиентСервер.ПодготовитьДанныеДокумента().
//  ПараметрыОперации 			- Структура, ФиксированнаяСтруктура - позволяет указать дополнительные параметры операции.
//			
// Возвращаемое значение:
//   см. СервисКриптографииDSSКлиентСервер.ОтветСервисаПоУмолчанию
//
Функция ПроверитьСертификат(ИдентификаторПользователя, ДанныеСертификата, ПараметрыОперации = Неопределено) Экспорт

	НовыеПараметры		 	= ПроверитьПараметрыОперации(ПараметрыОперации, "ТребуетАвторизации", Ложь);
	НастройкиПользователя	= ПолучитьНастройкиПользователя(ИдентификаторПользователя, НовыеПараметры);
	АдресПодключения 		= НастройкиПользователя.Методы.СервисПроверки + "certificates";
	СтруктураДокумента 		= СервисКриптографииDSSКлиентСервер.ПодготовитьДанныеДокумента(ДанныеСертификата);
	
	ПараметрыЗапроса = Новый Структура;
	ПараметрыЗапроса.Вставить("Content", СтруктураДокумента.Документ);
	
	РезультатЗапроса = ПодключитьВыполнитьМетодСервиса(НастройкиПользователя, АдресПодключения, ПараметрыЗапроса, "POST", "json", , НовыеПараметры);
	
	Если РезультатЗапроса.Выполнено Тогда
		
		Результат = РезультатЗапроса.Результат.Result;
		Если НЕ Результат Тогда
			СервисКриптографииDSSСлужебный.ПолучитьОписаниеОшибки(РезультатЗапроса, "ПроверкаСертификата", РезультатЗапроса.Результат.Message);
		КонецЕсли;
		РезультатЗапроса.Результат = Результат;
		
	КонецЕсли;
	
	СервисКриптографииDSSСлужебный.ПротоколОшибкиПриВызове(РезультатЗапроса, "ПроверитьСертификат", ПараметрыЗапроса, , ПараметрыОперации);
	
	Возврат РезультатЗапроса;

КонецФункции

// Формирует список подписантов для переданного документа, не работает для отделенной подписи
//
// Параметры:
//  ИдентификаторПользователя 	- Структура, СправочникСсылка.УчетныеЗаписиDSS - см. функцию НастройкиПользователяПоУмолчанию()
//  ДанныеДокумента 			- ДвоичныеДанные, Строка - один файл, который необходимо обработать,
//								см. функцию СервисКриптографииDSSКлиентСервер.ПодготовитьДанныеДокумента().
//  ТипПодписи 					- см. СервисКриптографииDSSКлиентСервер.ПолучитьТипыПодписей
//  ПараметрыОперации 			- Структура, ФиксированнаяСтруктура - позволяет указать дополнительные параметры операции.
//			
// Возвращаемое значение:
//   см. СервисКриптографииDSSКлиентСервер.ОтветСервисаПоУмолчанию
//
Функция ПолучитьСведенияОПодписантах(ИдентификаторПользователя, ДанныеДокумента, ТипПодписи = "CMS", ПараметрыОперации = Неопределено) Экспорт
	
	НовыеПараметры		 	= ПроверитьПараметрыОперации(ПараметрыОперации, "ТребуетАвторизации", Ложь);
	НастройкиПользователя	= ПолучитьНастройкиПользователя(ИдентификаторПользователя, НовыеПараметры);
	АдресПодключения 		= НастройкиПользователя.Методы.СервисПроверки + "signatures/signersInfo";
	СтруктураДокумента 		= СервисКриптографииDSSКлиентСервер.ПодготовитьДанныеДокумента(ДанныеДокумента);
	ИдТиповПодписей			= СервисКриптографииDSSКлиентСервер.ПолучитьТипыПодписей();
	
	ПараметрыЗапроса		= Новый Структура;
	ПараметрыЗапроса.Вставить("Content", СтруктураДокумента.Документ);
	ПараметрыЗапроса.Вставить("SignatureType", ИдТиповПодписей[ТипПодписи]);
	
	РезультатЗапроса = ПодключитьВыполнитьМетодСервиса(НастройкиПользователя, АдресПодключения, ПараметрыЗапроса, "POST", "json", , НовыеПараметры);
	
	Если РезультатЗапроса.Выполнено Тогда
		Результат = Новый Массив;
		МассивПодписей = СвойствоСтруктуры(РезультатЗапроса.Результат, "SignerInfoList", Новый Массив);
		Для каждого СтрокаМассива Из МассивПодписей Цикл
			ИндексПодписи	= СвойствоСтруктуры(СтрокаМассива, "Index", 0) + 1;
			Родитель		= СвойствоСтруктуры(СтрокаМассива, "ParentId", 0);
			Идентификатор	= СвойствоСтруктуры(СтрокаМассива, "Id", 0);
			СерийныйНомер 	= СвойствоСтруктуры(СтрокаМассива, "SignerCertificateInfo.SerialNumber", "");
			Отпечаток		= СвойствоСтруктуры(СтрокаМассива, "SignerCertificateInfo.Thumbprint", "");
			Издатель		= СвойствоСтруктуры(СтрокаМассива, "SignerCertificateInfo.IssuerName", "");
			ИмяСертификата	= СвойствоСтруктуры(СтрокаМассива, "SignerCertificateInfo.SubjectName", "");
			
			НоваяСтрока 	= Новый Структура();
			НоваяСтрока.Вставить("Индекс", ИндексПодписи);
			НоваяСтрока.Вставить("Идентификатор", Идентификатор);
			НоваяСтрока.Вставить("Родитель", Родитель);
			НоваяСтрока.Вставить("СерийныйНомер", НРег(СерийныйНомер));
			НоваяСтрока.Вставить("Отпечаток", НРег(Отпечаток));
			НоваяСтрока.Вставить("Издатель", Издатель);
			НоваяСтрока.Вставить("ИмяСертификата", ИмяСертификата);
			Результат.Добавить(НоваяСтрока);
		КонецЦикла;
		
		РезультатЗапроса.Вставить("Результат", Результат);
		
	КонецЕсли;	
	
	СервисКриптографииDSSСлужебный.ПротоколОшибкиПриВызове(РезультатЗапроса, "ПроверитьСертификат", ПараметрыЗапроса, , ПараметрыОперации);
	
	Возврат РезультатЗапроса;

КонецФункции

// Проверяет подпись документа в различных форматах.
// Для ГОСТ нужно передавать сертификат.
// Для отсоединенной подписи нужно передавать исходный документ и передать дополнительные свойства.
// Для хеш нужно передать дополнительные свойства.
//
// Параметры:
//  ИдентификаторПользователя 	- Структура, СправочникСсылка.УчетныеЗаписиDSS - см. функцию НастройкиПользователяПоУмолчанию()
//  ДанныеДокумента 			- ДвоичныеДанные, Строка - один файл, который необходимо обработать,
//								см. функцию СервисКриптографииDSSКлиентСервер.ПодготовитьДанныеДокумента().
//  ИсходныйДокумент 			- ДвоичныеДанные, Строка, Неопределено - один файл, который необходимо обработать при проверке подписи
//  ТипПодписи 					- см. СервисКриптографииDSSКлиентСервер.ПолучитьТипыПодписей
//  СвойстваПроверки 			- Структура - см. СервисКриптографииDSSКлиентСервер.ПолучитьСвойстваПроверкиПодписи,
//								см. функцию СервисКриптографииDSSКлиентСервер.ПодготовитьДанныеДокумента().
//  Сертификат 					- ДвоичныеДанные, Строка - один файл, содержит данные сертификата который необходимо проверить,
//								см. функцию СервисКриптографииDSSКлиентСервер.ПодготовитьДанныеДокумента().
//  ПараметрыОперации 			- Структура, ФиксированнаяСтруктура - позволяет указать дополнительные параметры операции.
//			
// Возвращаемое значение:
//   см. СервисКриптографииDSSКлиентСервер.ОтветСервисаПоУмолчанию
//
Функция ПроверитьПодпись(ИдентификаторПользователя,
						ДанныеДокумента,
						ИсходныйДокумент,
						ТипПодписи,
						СвойстваПроверки,
						Сертификат = Неопределено,
						ПараметрыОперации = Неопределено) Экспорт
	
	НовыеПараметры		 	= ПроверитьПараметрыОперации(ПараметрыОперации, "ТребуетАвторизации", Ложь);
	НастройкиПользователя	= ПолучитьНастройкиПользователя(ИдентификаторПользователя, НовыеПараметры);
	АдресПодключения 		= НастройкиПользователя.Методы.СервисПроверки + "signatures";
	ИдТиповПодписей			= СервисКриптографииDSSКлиентСервер.ПолучитьТипыПодписей();
	СтруктураДокумента 		= СервисКриптографииDSSКлиентСервер.ПодготовитьДанныеДокумента(ДанныеДокумента);
	
	ПараметрыЗапроса		= Новый Структура;
	ПараметрыЗапроса.Вставить("Content", СтруктураДокумента.Документ);
	ПараметрыЗапроса.Вставить("SignatureType", ИдТиповПодписей[ТипПодписи]);
	
	Если СвойстваПроверки <> Неопределено Тогда
		ПараметрыЗапроса.Вставить("VerifyParams", СвойстваПроверки);
	КонецЕсли;	
	
	Если ИсходныйДокумент <> Неопределено Тогда
		СтруктураДокумента 	= СервисКриптографииDSSКлиентСервер.ПодготовитьДанныеДокумента(ИсходныйДокумент);
		ПараметрыЗапроса.Вставить("Source", СтруктураДокумента.Документ);
	КонецЕсли;
	
	Если Сертификат <> Неопределено Тогда
		СтруктураДокумента 	= СервисКриптографииDSSКлиентСервер.ПодготовитьДанныеДокумента(Сертификат);
		ПараметрыЗапроса.Вставить("Certificate", СтруктураДокумента.Документ);
	КонецЕсли;
	
	РезультатЗапроса	= ПодключитьВыполнитьМетодСервиса(НастройкиПользователя, АдресПодключения, ПараметрыЗапроса, "POST", "json", , НовыеПараметры);
	МассивСертификатов	= Новый Массив;
	
	Если РезультатЗапроса.Выполнено Тогда
		
		ЕстьОшибка 	= Ложь;
		ОбщаяОшибка	= "";
		Для каждого СтрокаМассива Из РезультатЗапроса.Результат Цикл
			ЕстьОшибка 	= НЕ СтрокаМассива.Result ИЛИ ЕстьОшибка;
			Сертификат	= Base64Значение(СтрокаМассива.SignerCertificate);
			ОбщаяОшибка = ОбщаяОшибка + ?(ПустаяСтрока(ОбщаяОшибка), "", Символы.ПС) + СтрокаМассива.Message;
			Если Сертификат.Размер() > 0 Тогда
				ПроверкаСертификата = Новый Структура();
				ПроверкаСертификата.Вставить("ПодписьВалидна", СтрокаМассива.Result);
				ПроверкаСертификата.Вставить("Сертификат", Сертификат);
				ПроверкаСертификата.Вставить("Отпечаток", НРег(СвойствоСтруктуры(СтрокаМассива, "SignerCertificateInfo.Thumbprint", "")));
				МассивСертификатов.Добавить(ПроверкаСертификата);
			КонецЕсли;	
		КонецЦикла;
		
		Если ЕстьОшибка Тогда
			СервисКриптографииDSSСлужебный.ПолучитьОписаниеОшибки(РезультатЗапроса, "ПроверкаПодписи", ОбщаяОшибка);
		КонецЕсли;
		РезультатЗапроса.Вставить("Результат", НЕ ЕстьОшибка);
		
		РезультатЗапроса.Вставить("Сертификаты", МассивСертификатов);
		
	КонецЕсли;
	
	СервисКриптографииDSSСлужебный.ПротоколОшибкиПриВызове(РезультатЗапроса, "ПроверитьПодпись", ПараметрыЗапроса, , ПараметрыОперации);
	
	Возврат РезультатЗапроса;
	
КонецФункции

#КонецОбласти

#Область Аутентификация

// Выполняет аутентификацию пользователя в серверном контексте по сценарию "Авторизация с использованием учетных данных пользователя"
//
// Параметры:
//  ИдентификаторПользователя	- Структура, СправочникСсылка.УчетныеЗаписиDSS - см. функцию НастройкиПользователяПоУмолчанию()
//  ПараметрыОперации 			- Структура, ФиксированнаяСтруктура - позволяет указать дополнительные параметры операции.
//
// Возвращаемое значение:
//   см. СервисКриптографииDSSКлиентСервер.ОтветСервисаПоУмолчанию
//
Функция АутентификацияПоЛогину(ИдентификаторПользователя, ПараметрыОперации = Неопределено) Экспорт
	
	ВходящиеПараметры		= ПроверитьПараметрыОперации(ПараметрыОперации);
	Принудительно			= СвойствоСтруктуры(ВходящиеПараметры, "Принудительно", Ложь);
	НастройкиПользователя	= ПолучитьНастройкиПользователя(ИдентификаторПользователя, ВходящиеПараметры);
	ИсточникНастроек 		= СервисКриптографииDSSСлужебный.ПолучитьИсточникНастроек(ВходящиеПараметры);
	АдресПодключения 		= НастройкиПользователя.Методы.СервисИдентификации + "token";
	
	ПараметрыЗапроса	= Новый Структура;
	ПараметрыЗапроса.Вставить("client_id", НастройкиПользователя.Подключение.ИдентификаторКлиента);
	ПараметрыЗапроса.Вставить("username", НастройкиПользователя.Логин);
	ПараметрыЗапроса.Вставить("resource", НастройкиПользователя.Подключение.ИдентификаторПодписи);
	ПараметрыЗапроса.Вставить("grant_type", "password");
	ПараметрыЗапроса.Вставить("password", ПолучитьЗначениеПароля(НастройкиПользователя.Пароль, НастройкиПользователя));
	
	СвойстваПодключения	= СервисКриптографииDSSСлужебный.ПодготовитьСвойстваПодключения(НастройкиПользователя.Подключение, АдресПодключения);
	Соединение 			= СервисКриптографииDSSСлужебный.ПодготовитьПодключение(СвойстваПодключения, Неопределено, ПараметрыОперации);
	РезультатЗапроса	= СервисКриптографииDSSСлужебный.ВыполнитьМетодСервиса(Соединение, СвойстваПодключения.АдресПодключения, ПараметрыЗапроса, "POST", , , ПараметрыОперации);
	СохранитьНастройки	= Ложь;
	
	Если РезультатЗапроса.Выполнено Тогда
		РезультатЗапроса = ПроверитьМаркерДоступа(НастройкиПользователя, РезультатЗапроса, ПараметрыОперации);
		Если РезультатЗапроса.Выполнено Тогда
			СохранитьНастройки = Истина;
			РезультатЗапроса = ОбновитьПолитикуПользователя(НастройкиПользователя, Принудительно, ВходящиеПараметры);
			РезультатЗапроса.МаркерОбновлен = Истина;
			РезультатЗапроса.Вставить("НастройкиПользователя", НастройкиПользователя);
		КонецЕсли;	
	КонецЕсли;	
	
	Если СохранитьНастройки Тогда
		КлючНастроек = СервисКриптографииDSSКлиентСервер.КлючНастроекПользователя(НастройкиПользователя);
		СервисКриптографииDSSСлужебный.УстановитьНастройкиПользователя(КлючНастроек, НастройкиПользователя, ИсточникНастроек);
	КонецЕсли;
	
	СервисКриптографииDSSСлужебный.ПротоколОшибкиПриВызове(РезультатЗапроса, "АутентификацияПоЛогину", ПараметрыЗапроса, , ПараметрыОперации);
	
	Возврат РезультатЗапроса;
	
КонецФункции

// Выполняет аутентификацию пользователя по сценарию "Авторизация по сертификату" в серверном контексте
//
// Параметры:
//  ИдентификаторПользователя 	- Структура, СправочникСсылка.УчетныеЗаписиDSS - см. функцию НастройкиПользователяПоУмолчанию()
//  ПараметрыОперации 			- Структура, ФиксированнаяСтруктура - позволяет указать дополнительные параметры операции:
//    * СертификатАвторизации	- ДвоичныеДанные
//
// Возвращаемое значение:
//   см. СервисКриптографииDSSКлиентСервер.ОтветСервисаПоУмолчанию
//
Функция АутентификацияПоСертификату(ИдентификаторПользователя, ПараметрыОперации = Неопределено) Экспорт
	
	Результат 				= СервисКриптографииDSSКлиентСервер.ОтветСервисаПоУмолчанию(Ложь);
	ВходящиеПараметры		= ПроверитьПараметрыОперации(ПараметрыОперации);
	НастройкиПользователя	= ПолучитьНастройкиПользователя(ИдентификаторПользователя, ВходящиеПараметры);
	АдресПодключения 		= НастройкиПользователя.Методы.СервисИдентификации + "authorize/certificate";
	
	СертификатАвторизации	= СвойствоСтруктуры(ВходящиеПараметры, "СертификатАвторизации");
	Если СертификатАвторизации = Неопределено Тогда
		СертификатАвторизации	= СервисКриптографииDSSСлужебный.ПолучитьЗакрытыеДанные(
									НастройкиПользователя, 
									"СертификатАвторизации");
	КонецЕсли;
	
	Если НЕ ЗначениеЗаполнено(СертификатАвторизации) Тогда
		СервисКриптографииDSSСлужебный.ПолучитьОписаниеОшибки(Результат, "НеЗагруженСертификатАвторизации");
		Возврат Результат;	
	КонецЕсли;
	
	ВременныйФайл = ПолучитьИмяВременногоФайла("pfx");
	СертификатАвторизации.Записать(ВременныйФайл);
	
	СертификатКлиента	= Новый СертификатКлиентаФайл(ВременныйФайл, ПолучитьЗначениеПароля(НастройкиПользователя.ПарольСертификата, НастройкиПользователя));
	ПараметрыЗапроса	= Новый Структура;
	ПараметрыЗапроса.Вставить("client_id", НастройкиПользователя.Подключение.ИдентификаторКлиента);
	ПараметрыЗапроса.Вставить("response_type", "code");
	ПараметрыЗапроса.Вставить("scope", "dss+offline_access");
	ПараметрыЗапроса.Вставить("redirect_uri", НастройкиПользователя.Подключение.Заглушка);
	ПараметрыЗапроса.Вставить("resource", НастройкиПользователя.Подключение.ИдентификаторПодписи);
	ПараметрыЗапроса.Вставить("promt", "none");
	
	СвойстваПодключения	= СервисКриптографииDSSСлужебный.ПодготовитьСвойстваПодключения(НастройкиПользователя.Подключение, АдресПодключения);
	Соединение 			= СервисКриптографииDSSСлужебный.ПодготовитьПодключение(СвойстваПодключения, СертификатКлиента, ПараметрыОперации);
	РезультатЗапроса	= СервисКриптографииDSSСлужебный.ВыполнитьМетодСервиса(Соединение, СвойстваПодключения.АдресПодключения, ПараметрыЗапроса, "GET" , , , ПараметрыОперации);
	
	УдалитьФайлы(ВременныйФайл);
	
	Если РезультатЗапроса.Выполнено Тогда
		ПараметрыОтвета	= СервисКриптографииDSSСлужебный.ПолучитьПараметрыИзОтвета(РезультатЗапроса.Заголовки["Location"]);
		КодАвторизации	= ПараметрыОтвета["code"];
		Если КодАвторизации <> Неопределено Тогда
			Результат = ПолучитьТокенПоКодуАвторизации(КодАвторизации, НастройкиПользователя, ВходящиеПараметры);
			Результат.МаркерОбновлен = Истина;
			Результат.Вставить("НастройкиПользователя", НастройкиПользователя);
		Иначе
			СервисКриптографииDSSСлужебный.ПолучитьОписаниеОшибки(Результат, "ОшибкаТокена");
		КонецЕсли;
	Иначе
		Результат = РезультатЗапроса;
	КонецЕсли;	
	
	СервисКриптографииDSSСлужебный.ПротоколОшибкиПриВызове(Результат, "АутентификацияПоСертификату", ПараметрыЗапроса, , ПараметрыОперации);
	
	Возврат Результат;
	
КонецФункции

// Формирует адрес подключения для веб-формы
//
// Параметры:
//  ИдентификаторПользователя 	- Структура, СправочникСсылка.УчетныеЗаписиDSS - см. функцию НастройкиПользователяПоУмолчанию()
//  НеявныйТипРазрешения 		- Булево - включает режим неявного типа разрешения на сервере DSS
//  ПараметрыОперации 			- Структура, ФиксированнаяСтруктура - позволяет указать дополнительные параметры операции.
//
// Возвращаемое значение:
//  Строка - web-адрес для открытия HTML формы аутентификации
//
Функция ПолучитьАдресВебАутентификации(ИдентификаторПользователя, НеявныйТипРазрешения = Ложь, ПараметрыОперации = Неопределено) Экспорт
	
	НастройкиПользователя	= ПолучитьНастройкиПользователя(ИдентификаторПользователя, ПараметрыОперации);
	ПараметрыЗапроса 		= Новый Структура();
	ПараметрыЗапроса.Вставить("client_id", НастройкиПользователя.Подключение.ИдентификаторКлиента);
	ПараметрыЗапроса.Вставить("resource", НастройкиПользователя.Подключение.ИдентификаторПодписи);
	ПараметрыЗапроса.Вставить("scope", "dss+offline_access");
	ПараметрыЗапроса.Вставить("redirect_uri", НастройкиПользователя.Подключение.Заглушка);
	ПараметрыЗапроса.Вставить("login_hint", НастройкиПользователя.Логин);

	Если НЕ НеявныйТипРазрешения Тогда 
		ПараметрыЗапроса.Вставить("response_type", "code");
	Иначе
		ПараметрыЗапроса.Вставить("response_type", "token");
	КонецЕсли;	
	
	АдресПодключения	= НастройкиПользователя.Методы.СервисИдентификации + "authorize";
	СвойстваПодключения	= СервисКриптографииDSSСлужебный.ПодготовитьСвойстваПодключения(НастройкиПользователя.Подключение, АдресПодключения);
	
	ПараметрыАдреса = СервисКриптографииDSSСлужебный.ПротоколПодключения(СвойстваПодключения.ЗащищенноеСоединение) + "://" 
					+ СвойстваПодключения.Сервер + "/"
					+ СвойстваПодключения.АдресПодключения + "?" 
					+ СервисКриптографииDSSСлужебный.СтруктураВСтроку(ПараметрыЗапроса);
					
	Возврат ПараметрыАдреса;
					
КонецФункции

// Выполняет окончательный шаг аутентификации: получает токен по коду авторизации, 
// является продолжением других процессов аутентификации.
//
// Параметры:
//  КодАвторизации 				- Строка - маркер авторизации полученный на предыдущих шагах аутентификации
//  ИдентификаторПользователя 	- Структура, СправочникСсылка.УчетныеЗаписиDSS - см. функцию НастройкиПользователяПоУмолчанию()
//  ПараметрыОперации 			- Структура, ФиксированнаяСтруктура - позволяет указать дополнительные параметры операции.
//
// Возвращаемое значение:
//   см. СервисКриптографииDSSКлиентСервер.ОтветСервисаПоУмолчанию
//
Функция ПолучитьТокенПоКодуАвторизации(КодАвторизации, ИдентификаторПользователя = Неопределено, ПараметрыОперации = Неопределено) Экспорт
	
	ВходящиеПараметры		= ПроверитьПараметрыОперации(ПараметрыОперации);
	Принудительно			= СвойствоСтруктуры(ВходящиеПараметры, "Принудительно", Ложь);
	НастройкиПользователя	= ПолучитьНастройкиПользователя(ИдентификаторПользователя, ВходящиеПараметры);
	ИсточникНастроек 		= СервисКриптографииDSSСлужебный.ПолучитьИсточникНастроек(ВходящиеПараметры);
	АдресПодключения 		= НастройкиПользователя.Методы.СервисИдентификации + "token";
	СвойстваПодключения		= СервисКриптографииDSSСлужебный.ПодготовитьСвойстваПодключения(НастройкиПользователя.Подключение, АдресПодключения);
	
	ПараметрыЗапроса		= Новый Структура;
	ПараметрыЗапроса.Вставить("client_id", НастройкиПользователя.Подключение.ИдентификаторКлиента);
	ПараметрыЗапроса.Вставить("grant_type", "authorization_code");
	ПараметрыЗапроса.Вставить("code", КодАвторизации);
	ПараметрыЗапроса.Вставить("redirect_uri", НастройкиПользователя.Подключение.Заглушка);
	
	Соединение 			= СервисКриптографииDSSСлужебный.ПодготовитьПодключение(СвойстваПодключения, Неопределено, ПараметрыОперации);
	РезультатЗапроса	= СервисКриптографииDSSСлужебный.ВыполнитьМетодСервиса(Соединение, СвойстваПодключения.АдресПодключения, ПараметрыЗапроса, "POST", , , ПараметрыОперации);
	СохранитьНастройки	= Ложь;

	Если РезультатЗапроса.Выполнено Тогда
		РезультатЗапроса = ПроверитьМаркерДоступа(НастройкиПользователя, РезультатЗапроса, ПараметрыОперации);
		Если РезультатЗапроса.Выполнено Тогда
			СохранитьНастройки = Истина;
			РезультатЗапроса = ОбновитьПолитикуПользователя(НастройкиПользователя, Принудительно, ВходящиеПараметры);
			РезультатЗапроса.МаркерОбновлен = Истина;
			РезультатЗапроса.Вставить("НастройкиПользователя", НастройкиПользователя);
		КонецЕсли;	
	КонецЕсли;	
	
	Если СохранитьНастройки Тогда
		КлючНастроек = СервисКриптографииDSSКлиентСервер.КлючНастроекПользователя(НастройкиПользователя);
		СервисКриптографииDSSСлужебный.УстановитьНастройкиПользователя(КлючНастроек, НастройкиПользователя, ИсточникНастроек);
	КонецЕсли;
	
	СервисКриптографииDSSСлужебный.ПротоколОшибкиПриВызове(РезультатЗапроса, "ПолучитьТокенПоКодуАвторизации", ПараметрыЗапроса, , ПараметрыОперации);
	
	Возврат РезультатЗапроса;
	
КонецФункции

// Выполняет обновление токена авторизации в случае если токен обновления был получен из сервиса в предыдущих вызовах
//
// Параметры:
//  ИдентификаторПользователя 	- Структура, СправочникСсылка.УчетныеЗаписиDSS - см. функцию НастройкиПользователяПоУмолчанию()
//  ПараметрыОперации 			- Структура, ФиксированнаяСтруктура - позволяет указать дополнительные параметры операции.
//
// Возвращаемое значение:
//   см. СервисКриптографииDSSКлиентСервер.ОтветСервисаПоУмолчанию
//
Функция ОбновитьТокенАутентификации(ИдентификаторПользователя, ПараметрыОперации = Неопределено) Экспорт
	
	ВходящиеПараметры		= ПроверитьПараметрыОперации(ПараметрыОперации);
	Принудительно			= СвойствоСтруктуры(ВходящиеПараметры, "Принудительно", Ложь);
	НастройкиПользователя	= ПолучитьНастройкиПользователя(ИдентификаторПользователя, ВходящиеПараметры);
	ИсточникНастроек 		= СервисКриптографииDSSСлужебный.ПолучитьИсточникНастроек(ВходящиеПараметры);
	АдресПодключения 		= НастройкиПользователя.Методы.СервисИдентификации + "token";
	СвойстваПодключения		= СервисКриптографииDSSСлужебный.ПодготовитьСвойстваПодключения(НастройкиПользователя.Подключение, АдресПодключения);
	ТокенОбновления			= ПолучитьЗначениеПароля(НастройкиПользователя.ТокенАвторизации.ТокенОбновления, НастройкиПользователя);
	
	ПараметрыЗапроса	= Новый Структура;
	ПараметрыЗапроса.Вставить("client_id", НастройкиПользователя.Подключение.ИдентификаторКлиента);
	ПараметрыЗапроса.Вставить("grant_type", "refresh_token");
	ПараметрыЗапроса.Вставить("refresh_token", ТокенОбновления);
	
	Соединение 			= СервисКриптографииDSSСлужебный.ПодготовитьПодключение(СвойстваПодключения, Неопределено, ПараметрыОперации);
	РезультатЗапроса	= СервисКриптографииDSSСлужебный.ВыполнитьМетодСервиса(Соединение, СвойстваПодключения.АдресПодключения, ПараметрыЗапроса, "POST", , , ПараметрыОперации);
	СохранитьНастройки	= Ложь;
	
	Если РезультатЗапроса.Выполнено Тогда
		РезультатЗапроса = ПроверитьМаркерДоступа(НастройкиПользователя, РезультатЗапроса, ПараметрыОперации);
		Если РезультатЗапроса.Выполнено Тогда
			СохранитьНастройки = Истина;
			РезультатЗапроса.МаркерОбновлен = Истина;
		КонецЕсли;	
	КонецЕсли;	
	
	Если СохранитьНастройки Тогда
		РезультатЗапроса = ОбновитьПолитикуПользователя(НастройкиПользователя, Принудительно, ВходящиеПараметры);
		РезультатЗапроса.Вставить("НастройкиПользователя", НастройкиПользователя);
		КлючНастроек = СервисКриптографииDSSКлиентСервер.КлючНастроекПользователя(НастройкиПользователя);
		СервисКриптографииDSSСлужебный.УстановитьНастройкиПользователя(КлючНастроек, НастройкиПользователя, ИсточникНастроек);
	КонецЕсли;
	
	СервисКриптографииDSSСлужебный.ПротоколОшибкиПриВызове(РезультатЗапроса, "ОбновитьТокенАутентификации", ПараметрыЗапроса, , ПараметрыОперации);
	
	Возврат РезультатЗапроса;
	
КонецФункции

// Выполняет проверку аутентификации учетной записи на сервере DSS/
// При необходимости проводит первичную аутентификацию или обновляет маркер безопасности.
//
// Параметры:
//  ИдентификаторПользователя 	- Структура, СправочникСсылка.УчетныеЗаписиDSS - см. функцию НастройкиПользователяПоУмолчанию()
//  ПараметрыОперации 			- Структура, ФиксированнаяСтруктура - позволяет указать дополнительные параметры операции:
//    * ДатаСеанса 			- Дата
//    * ИсточникНастроек 		- Строка
//    * Принудительно			- Булево
//
// Возвращаемое значение:
//   см. СервисКриптографииDSSКлиентСервер.ОтветСервисаПоУмолчанию
//	
Функция ПроверитьАутентификацию(ИдентификаторПользователя, ПараметрыОперации = Неопределено) Экспорт
	
	НастройкиПользователя = ПолучитьНастройкиПользователя(ИдентификаторПользователя, ПараметрыОперации);
		
	ВидАутентификации = НастройкиПользователя.ПервичнаяАутентификация;
	ПарольПользователя = СвойствоСтруктуры(ПараметрыОперации, "Пароль");
	Принудительно = СвойствоСтруктуры(ПараметрыОперации, "Принудительно", Ложь);
	
	Если ЗначениеЗаполнено(ПарольПользователя) Тогда
		Если ВидАутентификации = Перечисления.СпособыАвторизацииDSS.Первичный_СертификатАвторизации Тогда
			НастройкиПользователя.ПарольСертификата = СервисКриптографииDSSКлиентСервер.ПодготовитьОбъектПароля(ПарольПользователя, 
								НастройкиПользователя.АвторизованныйПользователь);
		Иначе
			НастройкиПользователя.Пароль = СервисКриптографииDSSКлиентСервер.ПодготовитьОбъектПароля(ПарольПользователя, 
								НастройкиПользователя.АвторизованныйПользователь);
		КонецЕсли;
	КонецЕсли;	
	
	РезультатЗапроса = ПроверитьТокенАутентификации(НастройкиПользователя, Принудительно, ПараметрыОперации);
	
	СервисКриптографииDSSСлужебный.ПротоколОшибкиПриВызове(РезультатЗапроса, "ПроверкаАутентификации", Неопределено, , ПараметрыОперации);
	
	Возврат РезультатЗапроса;
	
КонецФункции

// Разбирает полученный токен авторизации (JWT), извлекает из него служебную информацию, проверяет на подмену логина
//
// Параметры:
//  НастройкиПользователя 	- см. НастройкиПользователяПоУмолчанию
//  РезультатЗапроса 		- Структура - дополняет переданную структуру ошибкой, если	маркер не соответствует ожидаемому логину:
//    * Выполнено 		- Булево - приравнивает Ложь
//    * Ошибка 			- Строка - заполняет описание ошибки
//    * КодОшибки			- Строка - заполняет код ошибки
//  ПараметрыОперации 		- Структура, ФиксированнаяСтруктура - позволяет указать дополнительные параметры операции.
//
// Возвращаемое значение:
//  Булево - Истина, если проверка пройдена
//
Функция ПроверитьМаркерДоступа(НастройкиПользователя, РезультатЗапроса, ПараметрыОперации = Неопределено) Экспорт
	
	Результат		= РезультатЗапроса;
	НовыеДанные		= РезультатЗапроса.Результат;
	
	ТокенАвторизации= НастройкиПользователя.ТокенАвторизации;
	ТекущийТокен 	= ПолучитьЗначениеПароля(ТокенАвторизации.Токен, НастройкиПользователя);
	НовыйТокен		= СвойствоСтруктуры(НовыеДанные, "AccessToken");
	Длительность	= 0;
	
	Если НовыйТокен <> Неопределено Тогда
		Длительность 	= СвойствоСтруктуры(НовыеДанные, "ExpiresIn", 0);
		Токен 			= НовыйТокен;
		ТипТокена 		= СвойствоСтруктуры(НовыеДанные, "tokentype", "Bearer");
		ТокенОбновления = СвойствоСтруктуры(НовыеДанные, "RefreshToken", "");
	Иначе
		Длительность 	= СвойствоСтруктуры(НовыеДанные, "Expires_In", 0);
		Токен 			= СвойствоСтруктуры(НовыеДанные, "Access_Token", "");
		ТипТокена 		= СвойствоСтруктуры(НовыеДанные, "token_type", "Bearer");
		ТокенОбновления = СвойствоСтруктуры(НовыеДанные, "Refresh_Token", "");
	КонецЕсли;
	
	ДанныеТокена = РазобратьТокенАвторизации(Токен, ПараметрыОперации);
	// добавить проверку на сервис ЦИ и логин, актуально для веб-авторизации
	Если ВРег(ДанныеТокена.Логин) = ВРег(НастройкиПользователя.Логин) Тогда
		ТокенАвторизации.Токен 			= СервисКриптографииDSSКлиентСервер.ОбъектПароля(Токен, 0);
		ТокенАвторизации.ТипТокена 		= ТипТокена;
		ТокенАвторизации.ТокенОбновления= СервисКриптографииDSSКлиентСервер.ОбъектПароля(ТокенОбновления, 0);
		НастройкиПользователя.ЭлектроннаяПочта = ДанныеТокена.ЭлектроннаяПочта;
		НастройкиПользователя.Телефон = ДанныеТокена.Телефон;
		НастройкиПользователя.ИдентификаторНаСервере = ДанныеТокена.Идентификатор;
		
		Если ТекущийТокен <> Токен Тогда
			ТокенАвторизации.СрокДействия = СервисКриптографииDSSСлужебный.ДатаСеанса() 
						+ Длительность;
		КонецЕсли;	
		
	Иначе
		Результат = СервисКриптографииDSSКлиентСервер.ОтветСервисаПоУмолчанию(Ложь);
		СервисКриптографииDSSСлужебный.ПолучитьОписаниеОшибки(Результат, "ПроверкаМаркерДоступа");
		
	КонецЕсли;	
	
	Возврат Результат;
	
КонецФункции

#КонецОбласти

#Область Сертификаты

// Обращение к сервису для установки сертификата. Допускает формат сертификата как в кодировке DER так и BER
//
// Параметры:
//  ИдентификаторПользователя 	- Структура, СправочникСсылка.УчетныеЗаписиDSS - см. функцию НастройкиПользователяПоУмолчанию()
//  ДанныеСертификата 			- ДвоичныеДанные, Строка - один файл, который необходимо обработать,
//								подробнее в СервисКриптографииDSSКлиентСервер.ПодготовитьДанныеДокумента().
//  ПараметрыОперации 			- Структура, ФиксированнаяСтруктура - позволяет указать дополнительные параметры операции.
//			
// Возвращаемое значение:
//   см. СервисКриптографииDSSКлиентСервер.ОтветСервисаПоУмолчанию
//
Функция УстановитьСертификат(ИдентификаторПользователя, ДанныеСертификата, ПараметрыОперации = Неопределено) Экспорт
	
	НастройкиПользователя	= ПолучитьНастройкиПользователя(ИдентификаторПользователя, ПараметрыОперации);
	ВерсияПодтверждения 	= СервисКриптографииDSSКлиентСервер.ИдентификаторВерсииСервера(НастройкиПользователя);
	
	Если ВерсияПодтверждения = 2 Тогда
		АдресПодключения 	= НастройкиПользователя.Методы.СервисПодписи20 + "certificates";
	Иначе
		АдресПодключения 	= НастройкиПользователя.Методы.СервисПодписи + "certificates";
	КонецЕсли;
	
	СтруктураДокумента		= СервисКриптографииDSSКлиентСервер.ПодготовитьДанныеДокумента(ДанныеСертификата);
	
	ПараметрыЗапроса		= Новый Структура;
	ПараметрыЗапроса.Вставить("certificate", СтруктураДокумента.Документ);
	
	РезультатЗапроса		= ПодключитьВыполнитьМетодСервиса(НастройкиПользователя, АдресПодключения, ПараметрыЗапроса, "POST", "json", , ПараметрыОперации);
	
	СервисКриптографииDSSСлужебный.ПротоколОшибкиПриВызове(РезультатЗапроса, "УстановитьСертификат", ПараметрыЗапроса, , ПараметрыОперации);
	
	Возврат РезультатЗапроса;
	
КонецФункции

// Получает данные одного и всех сертификатов учетной записи
//
// Параметры:
//  ИдентификаторПользователя 	- СправочникСсылка.УчетныеЗаписиDSS, Структура - см. функцию НастройкиПользователяПоУмолчанию()
//  ИдентификаторСертификата 	- Число - идентификатор сертификата в сервисе DSS
//  ПараметрыОперации 			- Структура, ФиксированнаяСтруктура - позволяет указать дополнительные параметры операции. Проверяются поля:
//    * ПроверитьНаличиеВБазе 	- Булево - синхронизировать получены данные с сервера с данным из РегистраСведений.СертификатыПользователяDSS
//			
// Возвращаемое значение:
//   см. СервисКриптографииDSSКлиентСервер.ОтветСервисаПоУмолчанию
//
Функция ПолучитьСертификатыСервиса(ИдентификаторПользователя, ИдентификаторСертификата = Неопределено, ПараметрыОперации = Неопределено) Экспорт
	
	ПроверитьНаличиеВБазе	= СвойствоСтруктуры(ПараметрыОперации, "ПроверитьНаличиеВБазе", Ложь);
	НастройкиПользователя	= ПолучитьНастройкиПользователя(ИдентификаторПользователя, ПараметрыОперации);
	ВерсияПодтверждения 	= СервисКриптографииDSSКлиентСервер.ИдентификаторВерсииСервера(НастройкиПользователя);
	
	Если ВерсияПодтверждения = 2 Тогда
		АдресПодключения 	= НастройкиПользователя.Методы.СервисПодписи20 + "certificates";
	Иначе
		АдресПодключения 	= НастройкиПользователя.Методы.СервисПодписи + "certificates";
	КонецЕсли;
	
	ВходящиеПараметры		= ПроверитьПараметрыОперации(ПараметрыОперации);
	ИсточникНастроек 		= СервисКриптографииDSSСлужебный.ПолучитьИсточникНастроек(ВходящиеПараметры);
	
	ОдинСертификат = Ложь;
	Если ЗначениеЗаполнено(ИдентификаторСертификата) Тогда
		АдресПодключения = АдресПодключения + "/" + Формат(ИдентификаторСертификата, "ЧГ=0");
		ОдинСертификат = Истина;
	КонецЕсли;
	
	ПараметрыЗапроса	= Новый Структура;
	РезультатЗапроса	= ПодключитьВыполнитьМетодСервиса(НастройкиПользователя, АдресПодключения, ПараметрыЗапроса, "GET", "json", , ПараметрыОперации);
	РезультатВыполнения = СервисКриптографииDSSКлиентСервер.ОтветСервисаПоУмолчанию();
	ЗаполнитьЗначенияСвойств(РезультатВыполнения, РезультатЗапроса);
	
	Если РезультатЗапроса.Выполнено Тогда
		// разбираем ответ и формируем результат
		СписокСертификатов = Новый Соответствие;
		
		Если ОдинСертификат Тогда
			МассивРезультата = Новый Массив;
			МассивРезультата.Добавить(РезультатЗапроса.Результат);
		Иначе
			МассивРезультата = РезультатЗапроса.Результат;
		КонецЕсли;
		
		ПаролиСертификатов = СервисКриптографииDSSСлужебный.ПолучитьЗакрытыеДанные(НастройкиПользователя, "Сертификаты");
		
		Для каждого СтрокаМассива Из МассивРезультата Цикл
			ДанныеСертификата	= СвойствоСтруктуры(СтрокаМассива, "CertificateBase64");
			СвойстваСертификата	= ПолучитьОбъектСертификата(Base64Значение(ДанныеСертификата));
			Издатель			= СвойствоСтруктуры(СвойстваСертификата, "Издатель.CN");
			ВнутреннийНомер 	= СвойствоСтруктуры(СтрокаМассива, "ID", 0);
			НуженПинКод			= СвойствоСтруктуры(СтрокаМассива, "HasPin", Ложь);
			ОтпечатокСертификата= НРег(СвойстваСертификата.Отпечаток);
			ОсновнойСертификат	= СвойствоСтруктуры(СтрокаМассива, "IsDefault", Ложь);
			АлгоритмыХеширования= СвойствоСтруктуры(СтрокаМассива, "HashAlgorithms", Новый Массив);
			КомуВыдан			= ЭлектроннаяПодпись.ПредставлениеСубъекта(СвойстваСертификата);
			ПарольСертификата	= СервисКриптографииDSSКлиентСервер.ПодготовитьОбъектПароля(
									ПаролиСертификатов[ОтпечатокСертификата], НастройкиПользователя.АвторизованныйПользователь, , ИсточникНастроек);
			Представление		= СвойствоСтруктуры(СтрокаМассива, "FriendlyName", "");
			Представление		= ?(ПустаяСтрока(Представление), СвойстваСертификата.Наименование, Представление);
			Представление		= ?(ПустаяСтрока(Представление), НСтр("ru = 'Не задано имя'"), Представление);
			
			НоваяСтрока			= СервисКриптографииDSSКлиентСервер.СвойстваСертификатаПользователя();
			НоваяСтрока.Идентификатор 	= ВнутреннийНомер;
			НоваяСтрока.Отпечаток 		= ОтпечатокСертификата;
			НоваяСтрока.ТребуетсяПинКод = НуженПинКод;
			НоваяСтрока.ПинКод 			= ПарольСертификата;
			НоваяСтрока.Основной 		= ОсновнойСертификат;
			НоваяСтрока.Представление 	= Представление;
			НоваяСтрока.Содержимое 		= ДанныеСертификата;
			НоваяСтрока.Издатель		= Издатель;
			НоваяСтрока.ДатаНачала		= СвойстваСертификата.ДатаНачала;
			НоваяСтрока.ДатаОкончания	= СвойстваСертификата.ДатаОкончания;
			НоваяСтрока.АлгоритмыХеширования = АлгоритмыХеширования;
			НоваяСтрока.КомуВыдан 		= КомуВыдан;
			
			СписокСертификатов.Вставить(ОтпечатокСертификата, НоваяСтрока);
		КонецЦикла;	
		
		Если ПроверитьНаличиеВБазе Тогда
			ПараметрыФоновогоЗадания = Новый Структура();
			ПараметрыФоновогоЗадания.Вставить("НастройкиПользователя", НастройкиПользователя);
			ПараметрыФоновогоЗадания.Вставить("СписокСертификатов", СписокСертификатов);
			
			СервисКриптографииDSSСлужебный.ВыполнитьВФоне("СервисКриптографииDSSСлужебный.ОбновитьКэшСертификатов", ПараметрыФоновогоЗадания);
			
			Для каждого СтрокаКлюча Из СписокСертификатов Цикл
				СтрокаКлюча.Значение.Содержимое = "";// для уменьшения размера сеансовых данных
			КонецЦикла;
			
		КонецЕсли;
		
		РезультатВыполнения.Вставить("Результат", СписокСертификатов);
		
	КонецЕсли;
	
	СервисКриптографииDSSСлужебный.ПротоколОшибкиПриВызове(РезультатВыполнения, "ПолучитьДанныеСертификатов", ПараметрыЗапроса, , ПараметрыОперации);
	
	Возврат РезультатВыполнения;
	
КонецФункции

// Проверяет валидность переданного пин-кода для указанного сертификата.
// Удобна в сценариях проверки пин-кода до выполнения самой криптографический операции.
//
// Параметры:
//  ИдентификаторПользователя 	- Структура, СправочникСсылка.УчетныеЗаписиDSS - см. функцию НастройкиПользователяПоУмолчанию()
//  ИдентификаторСертификата 	- Число - внутренний идентификатор сервиса, аналог кода справочника.
//  ПинКодСертификата 			- Строка - проверяемый пин-код
//  ПараметрыОперации 			- Структура, ФиксированнаяСтруктура - позволяет указать дополнительные параметры операции.
//
// Возвращаемое значение:
//   см. СервисКриптографииDSSКлиентСервер.ОтветСервисаПоУмолчанию.
//
Функция ВалидацияПинКодаСертификата(ИдентификаторПользователя, ИдентификаторСертификата, ПинКодСертификата = "", ПараметрыОперации = Неопределено) Экспорт
	
	НастройкиПользователя	= ПолучитьНастройкиПользователя(ИдентификаторПользователя, ПараметрыОперации);
	ВерсияПодтверждения 	= СервисКриптографииDSSКлиентСервер.ИдентификаторВерсииСервера(НастройкиПользователя);
	
	Если ВерсияПодтверждения = 2 Тогда
		АдресПодключения 	= НастройкиПользователя.Методы.СервисПодписи20 + "certificates/%1/pin/check";
	Иначе
		АдресПодключения 	= НастройкиПользователя.Методы.СервисПодписи + "certificates/%1/pin/check";
	КонецЕсли;
	
	АдресПодключения		= ЗаполнитьПараметрыСтроки(АдресПодключения, Формат(ИдентификаторСертификата, "ЧГ=0"));
	ВходящиеПараметры		= ПроверитьПараметрыОперации(ПараметрыОперации);
	ИсточникНастроек 		= СервисКриптографииDSSСлужебный.ПолучитьИсточникНастроек(ВходящиеПараметры);
	
	ПараметрыЗапроса	= Новый Структура;
	УстановитьПривилегированныйРежим(Истина);
	ПараметрыЗапроса.Вставить("Pin", ПолучитьЗначениеПароля(ПинКодСертификата, НастройкиПользователя, ИсточникНастроек));
	УстановитьПривилегированныйРежим(Ложь);
	ПараметрыЗапроса.Вставить("CheckAttempts", Истина);
	
	РезультатЗапроса	= ПодключитьВыполнитьМетодСервиса(НастройкиПользователя, АдресПодключения, ПараметрыЗапроса, "POST", "json", , ПараметрыОперации);
	
	Если РезультатЗапроса.Выполнено Тогда
		Если НЕ РезультатЗапроса.Результат.IsValid Тогда
			РезультатЗапроса.Выполнено = Ложь;
			СервисКриптографииDSSСлужебный.ПолучитьОписаниеОшибки(РезультатЗапроса, РезультатЗапроса.Результат.ErrorDescription);
		КонецЕсли;	
	КонецЕсли;
	
	СервисКриптографииDSSСлужебный.ПротоколОшибкиПриВызове(РезультатЗапроса, "ВалидацияПинКодаСертификата", ПараметрыЗапроса, , ПараметрыОперации);
	
	ПараметрыЗапроса = Неопределено;
	
	Возврат РезультатЗапроса
	
КонецФункции

// Смена пин-кода для указанного сертификата
//
// Параметры:
//  ИдентификаторПользователя 	- Структура, СправочникСсылка.УчетныеЗаписиDSS - см. функцию НастройкиПользователяПоУмолчанию()
//  ИдентификаторСертификата 	- Число - внутренний идентификатор сервиса, аналог кода справочника.
//  СтарыйПинКод 				- Строка - текущий пин-код, может быть пустой строкой
//  НовыйПинКод 				- Строка - устанавливаемый пин-код, может быть пустой строкой
//  ПараметрыОперации 			- Структура, ФиксированнаяСтруктура - позволяет указать дополнительные параметры операции.
//
// Возвращаемое значение:
//   см. СервисКриптографииDSSКлиентСервер.ОтветСервисаПоУмолчанию.
//
Функция СменитьПинКодСертификата(ИдентификаторПользователя, ИдентификаторСертификата, СтарыйПинКод, НовыйПинКод, ПараметрыОперации = Неопределено) Экспорт
	
	НастройкиПользователя	= ПолучитьНастройкиПользователя(ИдентификаторПользователя, ПараметрыОперации);
	ВерсияПодтверждения 	= СервисКриптографииDSSКлиентСервер.ИдентификаторВерсииСервера(НастройкиПользователя);
	ВходящиеПараметры		= ПроверитьПараметрыОперации(ПараметрыОперации);
	ИсточникНастроек 		= СервисКриптографииDSSСлужебный.ПолучитьИсточникНастроек(ВходящиеПараметры);
	ПодтверждениеОперации	= СвойствоСтруктуры(ПараметрыОперации, "ПодтверждатьПринудительно");
	
	Если ВерсияПодтверждения = 2 Тогда
		АдресПодключения 	= НастройкиПользователя.Методы.СервисПодписи20 + "certificates/%1/pin";
	Иначе
		АдресПодключения 	= НастройкиПользователя.Методы.СервисПодписи + "certificates/%1/pin";
	КонецЕсли;
	АдресПодключения		= ЗаполнитьПараметрыСтроки(АдресПодключения, Формат(ИдентификаторСертификата, "ЧГ=0"));
	
	ПараметрыЗапроса		= Новый Структура;
	УстановитьПривилегированныйРежим(Истина);
	ПараметрыЗапроса.Вставить("OldPin", ПолучитьЗначениеПароля(СтарыйПинКод, НастройкиПользователя, ИсточникНастроек));
	ПараметрыЗапроса.Вставить("NewPin", ПолучитьЗначениеПароля(НовыйПинКод, НастройкиПользователя, ИсточникНастроек));
	УстановитьПривилегированныйРежим(Ложь);
	
	Если ПодтверждениеОперации = Истина И ВерсияПодтверждения = 2 Тогда
		ПараметрыЗапроса.Вставить("ForceConfirmation", ПодтверждениеОперации);
	КонецЕсли;
	
	РезультатЗапроса	= ПодключитьВыполнитьМетодСервиса(НастройкиПользователя, АдресПодключения, ПараметрыЗапроса, "POST", "json", , ПараметрыОперации);
	Если РезультатЗапроса.Выполнено Тогда
		ДопПараметры = Новый Структура("ПроверитьНаличиеВБазе", Истина);
		РезультатОбновления = ПолучитьСертификатыСервиса(НастройкиПользователя, Неопределено, ДопПараметры);
		Если РезультатОбновления.Выполнено Тогда
			НастройкиПользователя.Сертификаты = РезультатОбновления.Результат;
			РезультатЗапроса.МаркерОбновлен = Истина;
			РезультатЗапроса.Вставить("НастройкиПользователя", НастройкиПользователя);
		КонецЕсли;
	КонецЕсли;
	
	Если ВерсияПодтверждения = 2 И РезультатЗапроса.Выполнено Тогда
		Выжимка = ОписаниеАсинхроннойОперации(РезультатЗапроса.Результат.Operation);
		РезультатОперации = Выжимка.ОписаниеОперации;
		Если НЕ Выжимка.Выполнено Тогда
			РезультатЗапроса.Выполнено = Ложь;
			РезультатЗапроса.Ошибка = Выжимка.Ошибка;
		КонецЕсли;
		РезультатЗапроса.Результат = РезультатОперации;
	КонецЕсли;
	
	СервисКриптографииDSSСлужебный.ПротоколОшибкиПриВызове(РезультатЗапроса, "СменитьПинКодСертификата", ПараметрыЗапроса, , ПараметрыОперации);
	
	ПараметрыЗапроса = Неопределено;
	
	Возврат РезультатЗапроса;
	
КонецФункции

// Установка основным (по-умолчанию)сертификата с указанным идентификатором
//
// Параметры:
//  ИдентификаторПользователя 	- Структура, СправочникСсылка.УчетныеЗаписиDSS - см. функцию НастройкиПользователяПоУмолчанию()
//  ИдентификаторСертификата 	- Число - внутренний идентификатор сервиса, аналог кода справочника.
//  Установить 					- Булево - установить сертификат основным или отменить.
//  ПараметрыОперации 			- Структура, ФиксированнаяСтруктура - позволяет указать дополнительные параметры операции.
//
// Возвращаемое значение:
//   см. СервисКриптографииDSSКлиентСервер.ОтветСервисаПоУмолчанию.
//
Функция НазначитьОсновнымСертификат(ИдентификаторПользователя, ИдентификаторСертификата, Установить = Истина, ПараметрыОперации = Неопределено) Экспорт
	
	НастройкиПользователя	= ПолучитьНастройкиПользователя(ИдентификаторПользователя, ПараметрыОперации);
	ВерсияПодтверждения 	= СервисКриптографииDSSКлиентСервер.ИдентификаторВерсииСервера(НастройкиПользователя);
	
	Если ВерсияПодтверждения = 2 Тогда
		АдресПодключения 	= НастройкиПользователя.Методы.СервисПодписи20 + "certificates/%1/default";
	Иначе		
		АдресПодключения 	= НастройкиПользователя.Методы.СервисПодписи + "certificates/%1/default";
	КонецЕсли;
	АдресПодключения		= ЗаполнитьПараметрыСтроки(АдресПодключения, Формат(ИдентификаторСертификата, "ЧГ=0"));
	
	ПараметрыЗапроса	= Новый Структура;
	ПараметрыЗапроса.Вставить("Default", Установить);
	
	РезультатЗапроса		= ПодключитьВыполнитьМетодСервиса(НастройкиПользователя, АдресПодключения, ПараметрыЗапроса, "POST", "json", , ПараметрыОперации);
	
	СервисКриптографииDSSСлужебный.ПротоколОшибкиПриВызове(РезультатЗапроса, "НазначитьОсновнымСертификат", ПараметрыЗапроса, , ПараметрыОперации);
	
	Возврат РезультатЗапроса;
	
КонецФункции

// Возвращает установленный на сервисе сертификат в виде объекта платформы: СертификатКриптографии
//
// Параметры:
//  ИдентификаторПользователя 	- Структура, СправочникСсылка.УчетныеЗаписиDSS - см. функцию НастройкиПользователяПоУмолчанию()
//  ИдентификаторСертификата 	- Число - внутренний идентификатор сервиса, аналог кода справочника.
//  ПараметрыОперации 			- Структура, ФиксированнаяСтруктура - позволяет указать дополнительные параметры операции.
//
// Возвращаемое значение:
//   см. СервисКриптографииDSSКлиентСервер.ОтветСервисаПоУмолчанию.
//
Функция ПолучитьДанныеСертификата(ИдентификаторПользователя, ИдентификаторСертификата, ПараметрыОперации = Неопределено) Экспорт
	
	НастройкиПользователя	= ПолучитьНастройкиПользователя(ИдентификаторПользователя, ПараметрыОперации);
	ТекущийСертификат 		= СервисКриптографииDSSКлиентСервер.НайтиСертификат(НастройкиПользователя, ИдентификаторСертификата);
	РезультатЗапроса		= ПолучитьСертификатыСервиса(НастройкиПользователя, ТекущийСертификат.Идентификатор);
	
	Если РезультатЗапроса.Выполнено Тогда
		Для каждого СтрокаКлюча Из РезультатЗапроса.Результат Цикл
			ДанныеСертификата = Base64Значение(СтрокаКлюча.Значение.Содержимое);
			РезультатЗапроса.Вставить("Результат", ПолучитьОбъектСертификата(ДанныеСертификата, Истина));
		КонецЦикла;	
	КонецЕсли;	
	
	Возврат РезультатЗапроса;
	
КонецФункции

// Возвращает структуру описание сертификата построенную на основе XML описания
//
// Параметры:
//  ИдентификаторПользователя 	- Структура, СправочникСсылка.УчетныеЗаписиDSS - см. функцию НастройкиПользователяПоУмолчанию()
//  ИдентификаторСертификата 	- Число - внутренний идентификатор сервиса, аналог кода справочника.
//  ПараметрыОперации 			- Структура, ФиксированнаяСтруктура - позволяет указать дополнительные параметры операции.
//
// Возвращаемое значение:
//   см. СервисКриптографииDSSКлиентСервер.ОтветСервисаПоУмолчанию.
//
Функция ПолучитьСвойстваСертификата(ИдентификаторПользователя, ИдентификаторСертификата, ПараметрыОперации = Неопределено) Экспорт
	
	НастройкиПользователя	= ПолучитьНастройкиПользователя(ИдентификаторПользователя, ПараметрыОперации);
	ВерсияПодтверждения 	= СервисКриптографииDSSКлиентСервер.ИдентификаторВерсииСервера(НастройкиПользователя);
	
	Если ТипЗнч(ИдентификаторСертификата) = Тип("Число") Тогда
		ИщемСертификат = ИдентификаторСертификата;
	Иначе
		ТекущийСертификат = СервисКриптографииDSSКлиентСервер.НайтиСертификат(НастройкиПользователя, ИдентификаторСертификата);
		ИщемСертификат = ТекущийСертификат.Идентификатор;
	КонецЕсли;	
	
	Если ВерсияПодтверждения = 2 Тогда
		АдресПодключения 	= НастройкиПользователя.Методы.СервисПодписи20 + "certificates/%1/content?format=%2";
	Иначе
		АдресПодключения 	= НастройкиПользователя.Методы.СервисПодписи + "certificates/%1/content?format=%2";
	КонецЕсли;
	АдресПодключения		= ЗаполнитьПараметрыСтроки(АдресПодключения, Формат(ИщемСертификат, "ЧГ=0"), 2);
	ПараметрыЗапроса		= Новый Структура;
	
	РезультатЗапроса		= ПодключитьВыполнитьМетодСервиса(НастройкиПользователя, АдресПодключения, ПараметрыЗапроса, "GET", "json", , ПараметрыОперации);
	
	Если РезультатЗапроса.Выполнено Тогда
		РезультатЗапроса.Результат = СервисКриптографииDSSСлужебный.ЗаполнитьСведенияСертификатаXMLОписание(РезультатЗапроса.Результат);
	КонецЕсли;
	
	СервисКриптографииDSSСлужебный.ПротоколОшибкиПриВызове(РезультатЗапроса, "ПолучитьСвойстваСертификата", ПараметрыЗапроса, , ПараметрыОперации);
	
	Возврат РезультатЗапроса;
	
КонецФункции

#КонецОбласти

#Область ЗапросыНаСертификат

// Обращение к сервису для генерации закрытого ключа и формирование содержимого запроса на сертификат PKSC10
//
// Параметры:
//  ИдентификаторПользователя 	- Структура, СправочникСсылка.УчетныеЗаписиDSS - см. функцию НастройкиПользователяПоУмолчанию()
//  УдостоверяющийЦентр 		- Число - идентификатор удостоверяющего центра зарегистрированного в сервисе
//  КриптоПровайдер 			- Строка - идентификатор криптопровайдера зарегистрированного в сервисе
//  ШаблонСертификата 			- Строка - шаблон используемый при создании запроса на сертификат, который зарегистрирован в сервисе
//  ПоляАтрибутов 				- Соответствие - перечисление полей, которые используются при формировании запроса на сертификат,
//								ключом является OID поля.
//  ПинКод 						- Строка - значение пин-кода для создаваемого закрытого ключа
//  ПараметрыОперации 			- Структура, ФиксированнаяСтруктура - позволяет указать дополнительные параметры операции.
//			
// Возвращаемое значение:
//   см. СервисКриптографииDSSКлиентСервер.ОтветСервисаПоУмолчанию
//
Функция СоздатьЗапросНаСертификат(ИдентификаторПользователя,
								УдостоверяющийЦентр,
								КриптоПровайдер,
								ШаблонСертификата,
								ПоляАтрибутов,
								ПинКод = "",
								ПараметрыОперации = Неопределено) Экспорт
	
	НастройкиПользователя	= ПолучитьНастройкиПользователя(ИдентификаторПользователя, ПараметрыОперации);
	ВходящиеПараметры		= ПроверитьПараметрыОперации(ПараметрыОперации);
	ИсточникНастроек 		= СервисКриптографииDSSСлужебный.ПолучитьИсточникНастроек(ВходящиеПараметры);
	ВерсияПодтверждения 	= СервисКриптографииDSSКлиентСервер.ИдентификаторВерсииСервера(НастройкиПользователя);
	ЭтоТранзакция			= СвойствоСтруктуры(ПараметрыОперации, "Транзакция", Ложь);
	ПодтверждениеОперации	= СвойствоСтруктуры(ПараметрыОперации, "ПодтверждатьПринудительно");
	УстановитьПривилегированныйРежим(Истина);
	ЗначениеПинКода			= ПолучитьЗначениеПароля(ПинКод, НастройкиПользователя, ИсточникНастроек);
	УстановитьПривилегированныйРежим(Ложь);
	
	Если ВерсияПодтверждения = 2 Тогда
		АдресПодключения 	= НастройкиПользователя.Методы.СервисПодписи20 + "requests";
	Иначе
		АдресПодключения 	= НастройкиПользователя.Методы.СервисПодписи + "requests";
	КонецЕсли;
	
	ПараметрыЗапроса		= Новый Структура;
	
	Если ВерсияПодтверждения = 1 ИЛИ НЕ ЭтоТранзакция Тогда
		ДопПараметры = СвойствоСтруктуры(ПараметрыОперации, "ДополнительныеПараметры", Новый Структура);
		
		Если ВерсияПодтверждения = 2 Тогда
			ПараметрыЗапроса.Вставить("AuthorityId", УдостоверяющийЦентр);
			ДопПараметры.Вставить("TemplateOid", ШаблонСертификата);
		ИначеЕсли НЕ ЭтоТранзакция Тогда
			ПараметрыЗапроса.Вставить("AuthorityId", УдостоверяющийЦентр);
			ПараметрыЗапроса.Вставить("Template", ШаблонСертификата);
			ДопПараметры.Вставить("GroupId", КриптоПровайдер);
		КонецЕсли;
		
		Если ЗначениеЗаполнено(ЗначениеПинКода) Тогда
			ПараметрыЗапроса.Вставить("PinCode", ЗначениеПинКода);
		КонецЕсли;	
		ПараметрыЗапроса.Вставить("DistinguishedName", ПоляАтрибутов);
		ПараметрыЗапроса.Вставить("Parameters", ДопПараметры);
		
		Если ПодтверждениеОперации = Истина И ВерсияПодтверждения = 2 Тогда
			ПараметрыЗапроса.Вставить("ForceConfirmation", ПодтверждениеОперации);
		КонецЕсли;
		
	ИначеЕсли ВерсияПодтверждения = 2 Тогда
		ПараметрыЗапроса = "{}";
		
	КонецЕсли;
	
	РезультатЗапроса = ПодключитьВыполнитьМетодСервиса(НастройкиПользователя, АдресПодключения, ПараметрыЗапроса, "POST", "json", , ПараметрыОперации);
	
	Если РезультатЗапроса.Выполнено И ВерсияПодтверждения = 2 Тогда
		Выжимка = ОписаниеАсинхроннойОперации(РезультатЗапроса.Результат.Operation);
		РезультатОперации = Выжимка.ОписаниеОперации;
		Если НЕ Выжимка.Выполнено Тогда
			РезультатЗапроса.Выполнено = Ложь;
			РезультатЗапроса.Ошибка = Выжимка.Ошибка;
		ИначеЕсли РезультатОперации.ТребуетПодтверждения Тогда
			РезультатЗапроса.Результат = РезультатОперации;
		Иначе
			РезультатЗапроса.Результат = СвойстваЗапросаНаСертификат(РезультатЗапроса.Результат.Operation.Result);
		КонецЕсли;
	ИначеЕсли РезультатЗапроса.Выполнено Тогда
		РезультатЗапроса.Результат = СвойстваЗапросаНаСертификат(РезультатЗапроса.Результат);
	КонецЕсли;
	
	СервисКриптографииDSSСлужебный.ПротоколОшибкиПриВызове(РезультатЗапроса, "СоздатьЗапросНаСертификат", ПараметрыЗапроса, , ПараметрыОперации);
	
	ПараметрыЗапроса = Неопределено;
	ЗначениеПинКода = Неопределено;
	
	Возврат РезультатЗапроса;
	
КонецФункции

// Обращение к сервису для получения реестра запросов на сертификат.
//
// Параметры:
//  ИдентификаторПользователя 	- Структура, СправочникСсылка.УчетныеЗаписиDSS - см. НастройкиПользователяПоУмолчанию()
//  ПараметрыОперации 			- Структура, ФиксированнаяСтруктура - позволяет указать дополнительные параметры операции:
//    * ТолькоАктуальные		- Булево - проверяемое поле по умолчанию Истина, список включает только запросы, которые
//    							 еще не обработаны.
//			
// Возвращаемое значение:
//   см. СервисКриптографииDSSКлиентСервер.ОтветСервисаПоУмолчанию
//
Функция СписокЗапросовНаСертификат(ИдентификаторПользователя,
								ПараметрыОперации = Неопределено) Экспорт
	
	НастройкиПользователя	= ПолучитьНастройкиПользователя(ИдентификаторПользователя, ПараметрыОперации);
	ВерсияПодтверждения 	= СервисКриптографииDSSКлиентСервер.ИдентификаторВерсииСервера(НастройкиПользователя);
	
	Если ВерсияПодтверждения = 2 Тогда
		АдресПодключения 	= НастройкиПользователя.Методы.СервисПодписи20 + "requests";
	Иначе
		АдресПодключения 	= НастройкиПользователя.Методы.СервисПодписи + "requests";
	КонецЕсли;
	
	ТолькоАктуальные		= СвойствоСтруктуры(ПараметрыОперации, "ТолькоАктуальные", Истина);
	ПараметрыЗапроса		= Новый Структура;
	РезультатЗапроса		= ПодключитьВыполнитьМетодСервиса(НастройкиПользователя, АдресПодключения, ПараметрыЗапроса, "GET", "json", , ПараметрыОперации);
	
	Если РезультатЗапроса.Выполнено Тогда
		Результат = Новый Массив;
		
		Для Каждого СтрокаМассива Из РезультатЗапроса.Результат Цикл
			ДанныеЗапроса = СвойстваЗапросаНаСертификат(СтрокаМассива);
			Если НЕ ТолькоАктуальные ИЛИ ДанныеЗапроса.Статус = "Обрабатывается" Тогда
				Результат.Добавить(ДанныеЗапроса);
			КонецЕсли;	
		КонецЦикла;
		
		РезультатЗапроса.Вставить("Результат", Результат);
		
	КонецЕсли;
	
	СервисКриптографииDSSСлужебный.ПротоколОшибкиПриВызове(РезультатЗапроса, "СоздатьЗапросНаСертификат", ПараметрыЗапроса, , ПараметрыОперации);
	
	Возврат РезультатЗапроса;
	
КонецФункции

// Получает свойства ранее созданного запроса на сертификат.
//
// Параметры:
//  ИдентификаторПользователя 	- Структура, СправочникСсылка.УчетныеЗаписиDSS - см. НастройкиПользователяПоУмолчанию()
//  ИдентификаторЗапроса		- Число - идентификатор запроса на сертификат, назначенный ему при создании
//  ПараметрыОперации 			- Структура, ФиксированнаяСтруктура - позволяет указать дополнительные параметры операции.
//			
// Возвращаемое значение:
//   см. СервисКриптографииDSSКлиентСервер.ОтветСервисаПоУмолчанию
//
Функция ПолучитьЗапросНаСертификат(ИдентификаторПользователя, 
								ИдентификаторЗапроса, 
								ПараметрыОперации = Неопределено) Экспорт
	
	НастройкиПользователя	= ПолучитьНастройкиПользователя(ИдентификаторПользователя, ПараметрыОперации);
	ВерсияПодтверждения 	= СервисКриптографииDSSКлиентСервер.ИдентификаторВерсииСервера(НастройкиПользователя);
	
	Если ВерсияПодтверждения = 2 Тогда
		АдресПодключения 	= НастройкиПользователя.Методы.СервисПодписи20 + "requests/%1";
	Иначе
		АдресПодключения 	= НастройкиПользователя.Методы.СервисПодписи + "requests/%1";
	КонецЕсли;
	АдресПодключения		= ЗаполнитьПараметрыСтроки(АдресПодключения, Формат(ИдентификаторЗапроса, "ЧГ=0"));
	ПараметрыЗапроса		= Новый Структура;
	
	РезультатЗапроса		= ПодключитьВыполнитьМетодСервиса(НастройкиПользователя, АдресПодключения, ПараметрыЗапроса, "GET", "json", , ПараметрыОперации);
	
	Если РезультатЗапроса.Выполнено Тогда
		Результат = СвойстваЗапросаНаСертификат(РезультатЗапроса.Результат);
		РезультатЗапроса.Результат = Результат;
	КонецЕсли;
	
	СервисКриптографииDSSСлужебный.ПротоколОшибкиПриВызове(РезультатЗапроса, "СоздатьЗапросНаСертификат", ПараметрыЗапроса, , ПараметрыОперации);
	
	Возврат РезультатЗапроса;
	
КонецФункции

// Удаляет ранее созданный запрос на сертификат на сервере.
//
// Параметры:
//  ИдентификаторПользователя 	- Структура, СправочникСсылка.УчетныеЗаписиDSS - см. функцию НастройкиПользователяПоУмолчанию()
//  ИдентификаторЗапроса		- Число - идентификатор запроса на сертификат, назначенный ему при создании
//  ПараметрыОперации 			- Структура, ФиксированнаяСтруктура - позволяет указать дополнительные параметры операции.
//			
// Возвращаемое значение:
//   см. СервисКриптографииDSSКлиентСервер.ОтветСервисаПоУмолчанию
//
Функция УдалитьЗапросНаСертификат(ИдентификаторПользователя, 
								ИдентификаторЗапроса, 
								ПараметрыОперации = Неопределено) Экспорт
	
	НастройкиПользователя	= ПолучитьНастройкиПользователя(ИдентификаторПользователя, ПараметрыОперации);
	ВерсияПодтверждения 	= СервисКриптографииDSSКлиентСервер.ИдентификаторВерсииСервера(НастройкиПользователя);
	
	Если ВерсияПодтверждения = 2 Тогда
		АдресПодключения 	= НастройкиПользователя.Методы.СервисПодписи20 + "requests/%1";
	Иначе
		АдресПодключения 	= НастройкиПользователя.Методы.СервисПодписи + "requests/%1";
	КонецЕсли;
	АдресПодключения		= ЗаполнитьПараметрыСтроки(АдресПодключения, Формат(ИдентификаторЗапроса, "ЧГ=0"));
	ПараметрыЗапроса		= Новый Структура;
	
	РезультатЗапроса		= ПодключитьВыполнитьМетодСервиса(НастройкиПользователя, АдресПодключения, ПараметрыЗапроса, "DELETE", "json", , ПараметрыОперации);
	
	Если РезультатЗапроса.Выполнено Тогда
		РезультатЗапроса.Результат = Истина;
	Иначе
		РезультатЗапроса.Результат = Ложь;
	КонецЕсли;
	
	СервисКриптографииDSSСлужебный.ПротоколОшибкиПриВызове(РезультатЗапроса, "СоздатьЗапросНаСертификат", ПараметрыЗапроса, , ПараметрыОперации);
	
	Возврат РезультатЗапроса;
	
КонецФункции

#КонецОбласти

#Область СервисныеФункции

// Получает доступные настройки политики для указанного пользователя (требует предварительной авторизации)
//
// Параметры:
//  НастройкиПользователя 	- Структура, СправочникСсылка.УчетныеЗаписиDSS - см. функцию НастройкиПользователяПоУмолчанию()
//  ПараметрыОперации 		- Структура, ФиксированнаяСтруктура - позволяет указать дополнительные параметры операции.
//
// Возвращаемое значение:
//   см. СервисКриптографииDSSКлиентСервер.ОтветСервисаПоУмолчанию
//
Функция ПолучитьПараметрыПолитики(НастройкиПользователя, ПараметрыОперации = Неопределено) Экспорт
	
	НастройкиПользователя	= ПолучитьНастройкиПользователя(НастройкиПользователя, ПараметрыОперации);
	АдресПодключения 		= НастройкиПользователя.Методы.СервисПодписи + "policy";
	СвойстваПодключения		= СервисКриптографииDSSСлужебный.ПодготовитьСвойстваПодключения(НастройкиПользователя.Подключение, АдресПодключения);
	Токен					= ПолучитьЗначениеПароля(НастройкиПользователя.ТокенАвторизации.Токен, НастройкиПользователя);
	
	ПараметрыЗапроса		= Новый Структура;
	Заголовки				= Новый Соответствие;
	Заголовки.Вставить("Authorization", НастройкиПользователя.ТокенАвторизации.ТипТокена + " "
										+ Токен);
	
	Соединение			= СервисКриптографииDSSСлужебный.ПодготовитьПодключение(СвойстваПодключения, Неопределено, ПараметрыОперации);
	РезультатЗапроса	= СервисКриптографииDSSСлужебный.ВыполнитьМетодСервиса(Соединение, СвойстваПодключения.АдресПодключения, ПараметрыЗапроса, "GET", Заголовки, "json_list", ПараметрыОперации);
	
	СервисКриптографииDSSСлужебный.ПротоколОшибкиПриВызове(РезультатЗапроса, "ПолучитьПараметрыПолитики", ПараметрыЗапроса, , ПараметрыОперации);
	
	Возврат РезультатЗапроса;
	
КонецФункции

// Создает транзакцию на сервере DSS c передачей необходимых данных. 
// Данный функционал требуется, если в настройках пользователя для выполнения операций используется режим.
// подтверждения с использованием вторичной авторизации: SMS, Email, мобильные приложения.
//
// Параметры:
//  ИдентификаторПользователя 	- Структура, СправочникСсылка.УчетныеЗаписиDSS - см. функцию НастройкиПользователяПоУмолчанию()
//  ДанныеЗапроса 				- Структура - специфические поля передаваемые для создания транзакции
//  КодОперации 				- Число - код вида создаваемой транзакции, список всех кодов заполняется в момент получения политики пользователя
//  ДанныеДокумента 			- ДвоичныеДанные, Строка, Массив - для некоторых видов транзакций необходимо передавать данные для обработки, 
//  							см. также СервисКриптографииDSSКлиентСервер.ПодготовитьДанныеДокумента.
//  ПараметрыОперации 			- Структура, ФиксированнаяСтруктура - позволяет указать дополнительные параметры операции.
//
// Возвращаемое значение:
//   см. СервисКриптографииDSSКлиентСервер.ОтветСервисаПоУмолчанию
//
Функция СоздатьТранзакцию(ИдентификаторПользователя, ДанныеЗапроса, КодОперации, ДанныеДокумента = Неопределено, ПараметрыОперации = Неопределено) Экспорт 
	
	НастройкиПользователя	= ПолучитьНастройкиПользователя(ИдентификаторПользователя, ПараметрыОперации);
	АдресПодключения 		= НастройкиПользователя.Методы.СервисПодписи + "transactions";
	
	ДополнительныеПараметры = ДанныеЗапроса;
	Если ТипЗнч(ДанныеЗапроса) = Тип("Структура") Тогда
		ДополнительныеПараметры = Новый Массив;
		Для каждого СтрокаКлюча Из ДанныеЗапроса Цикл
			НоваяСтрока = Новый Структура("Name, Value", СтрокаКлюча.Ключ, XMLСтрока(СтрокаКлюча.Значение));
			ДополнительныеПараметры.Добавить(НоваяСтрока);
		КонецЦикла;	
	КонецЕсли;
	
	Если ТипЗнч(ДополнительныеПараметры) = Тип("Массив") И (КодОперации = 2 ИЛИ КодОперации = 4) Тогда
		Для каждого СтрокаМассива Из ДополнительныеПараметры Цикл
			СтрокаМассива.Value = ПроверитьПараметрПодписи(НастройкиПользователя, СтрокаМассива.Name, СтрокаМассива.Value);
		КонецЦикла;
	КонецЕсли;

	ВозвращатьКак		= Новый Массив;
	СтруктураДокумента	= Новый Структура;
	ПараметрыЗапроса 	= Новый Структура;
	ПараметрыЗапроса.Вставить("OperationCode", КодОперации);
	ПараметрыЗапроса.Вставить("Parameters", ДополнительныеПараметры);
	
	Если ТипЗнч(ДанныеДокумента) = Тип("Массив") Тогда
		ДокументыДляОбработки = СервисКриптографииDSSКлиентСервер.ПодготовитьПакетДляПодписи(ДанныеДокумента);
		МассивДокументов = Новый Массив;
		Для каждого СтрокаМассива Из ДокументыДляОбработки Цикл
			СтруктураДокумента		= СервисКриптографииDSSКлиентСервер.ПодготовитьДанныеДокумента(СтрокаМассива.Content);
			НоваяСтрока = Новый Структура("Name, Content", СтрокаМассива.Name, СтруктураДокумента.Документ);
			МассивДокументов.Добавить(НоваяСтрока);
			ВозвращатьКак.Добавить(СтрокаМассива.ВернутьКак);
		КонецЦикла;	
		ПараметрыЗапроса.Вставить("Documents", МассивДокументов);
		
	ИначеЕсли ДанныеДокумента <> Неопределено Тогда
		СтруктураДокумента		= СервисКриптографииDSSКлиентСервер.ПодготовитьДанныеДокумента(ДанныеДокумента);
		ПараметрыЗапроса.Вставить("Document", СтруктураДокумента.Документ);
		ВозвращатьКак = СтруктураДокумента.ТипДокумента;
		
	КонецЕсли;
	
	РезультатЗапроса	= ПодключитьВыполнитьМетодСервиса(ИдентификаторПользователя, АдресПодключения, ПараметрыЗапроса, "POST", "json", , ПараметрыОперации);
	
	Если РезультатЗапроса.Выполнено Тогда
		РезультатЗапроса.Вставить("ТипРезультата", ВозвращатьКак);
	КонецЕсли;	
	
	СервисКриптографииDSSСлужебный.ПротоколОшибкиПриВызове(РезультатЗапроса, "СоздатьТранзакцию", ПараметрыЗапроса, , ПараметрыОперации);
	
	Возврат РезультатЗапроса;
	
КонецФункции

// Заполняет структуру НастройкиПользователя данными из сервиса: настроенная политика и список сертификатов учетной записи
//
// Параметры:
//  ИдентификаторПользователя 	- Структура, СправочникСсылка.УчетныеЗаписиDSS - см. функцию НастройкиПользователяПоУмолчанию()
//  Принудительно 				- Булево - принудительный запрос к сервису для повторного получения данных об учетной записи
//  ПараметрыОперации 			- Структура, ФиксированнаяСтруктура - позволяет указать дополнительные параметры операции.
//
// Возвращаемое значение:
//   см. СервисКриптографииDSSКлиентСервер.ОтветСервисаПоУмолчанию
//
Функция ОбновитьПолитикуПользователя(ИдентификаторПользователя, Принудительно = Ложь, ПараметрыОперации = Неопределено) Экспорт
	
	НастройкиПользователя = ПолучитьНастройкиПользователя(ИдентификаторПользователя, ПараметрыОперации);
	РезультатВызова = СервисКриптографииDSSКлиентСервер.ОтветСервисаПоУмолчанию(Ложь);
	
 	Если НЕ НастройкиПользователя.Политика.Заполнено ИЛИ Принудительно Тогда
		
		Удачно			= Ложь;
		РезультатЗапроса= ПолучитьПараметрыПолитики(НастройкиПользователя, ПараметрыОперации);
	
		Если РезультатЗапроса.Выполнено Тогда
			СервисКриптографииDSSСлужебный.НастройкиРаботыАнализПолитикиПользователя(НастройкиПользователя.Политика, РезультатЗапроса.Результат);
		КонецЕсли;	
		
		ПараметрыПоиска	= Новый Структура("ПроверитьНаличиеВБазе", ЗначениеЗаполнено(НастройкиПользователя.Ссылка));
		РезультатЗапроса= ПолучитьСертификатыСервиса(НастройкиПользователя, Неопределено, ПараметрыПоиска);
	
		Если РезультатЗапроса.Выполнено Тогда
			НастройкиПользователя.Сертификаты = РезультатЗапроса.Результат;
			Удачно = Истина;
		КонецЕсли;	
		
		РезультатВызова.Выполнено = Удачно;
		
	Иначе	
		РезультатВызова.Выполнено = Истина;
		
	КонецЕсли;
	
	СервисКриптографииDSSСлужебный.ПротоколОшибкиПриВызове(РезультатВызова, "ОбновитьПолитикуПользователя", "", , ПараметрыОперации);
	
	Возврат РезультатВызова;
	
КонецФункции

// Данная функция служит для получения список сервисов DSS (ЦИ и СЭП) доступных на указанном адресе сервера
//
// Параметры:
//  АдресСервера 		- Строка - адрес сервера с опубликованной информацией о списках ЦИ и СЭП
//  ПараметрыОперации 	- Структура, ФиксированнаяСтруктура - позволяет указать дополнительные параметры операции.
//
// Возвращаемое значение:
//   см. СервисКриптографииDSSКлиентСервер.ОтветСервисаПоУмолчанию
//
Функция ПолучитьОписаниеСервиса(АдресСервера, ПараметрыОперации = Неопределено) Экспорт
	
	СоставАдреса = ОбщегоНазначенияКлиентСервер.СтруктураURI(АдресСервера);
	АдресПодключения 	= ".well-known/webfinger";
	
	СвойстваПодключения = Новый Структура;
	СвойстваПодключения.Вставить("Сервер", СоставАдреса.ИмяСервера);
	СвойстваПодключения.Вставить("Порт", СоставАдреса.Порт);
	СвойстваПодключения.Вставить("ЗащищенноеСоединение", НРег(СоставАдреса.Схема) = "https");
	СвойстваПодключения.Вставить("ТаймАут", 20);
	
	ПараметрыЗапроса	= Новый Структура();
	ПараметрыЗапроса.Вставить("resource", АдресСервера);
	
	Соединение 			= СервисКриптографииDSSСлужебный.ПодготовитьПодключение(СвойстваПодключения, Неопределено, ПараметрыОперации);
	РезультатЗапроса	= СервисКриптографииDSSСлужебный.ВыполнитьМетодСервиса(Соединение, АдресПодключения, ПараметрыЗапроса, "GET", , "text", ПараметрыОперации);
	
	Если РезультатЗапроса.Выполнено Тогда
		Результат = СервисКриптографииDSSСлужебный.РазобратьОтветСервисаОбнаружения(РезультатЗапроса.Результат);
		РезультатЗапроса.Результат = Результат;
	КонецЕсли;	
	
	СервисКриптографииDSSСлужебный.ПротоколОшибкиПриВызове(РезультатЗапроса, "ПолучитьОписаниеСервиса", ПараметрыЗапроса, , ПараметрыОперации);
	
	Возврат РезультатЗапроса;
	
КонецФункции

// Выполняет произвольный запрос к сервису по переданным параметрам запроса
//
// Параметры:
//  НастройкиПользователя 	- см. НастройкиПользователяПоУмолчанию
//  АдресПодключения 		- Строка - адрес для выполнения запроса
//  ПараметрыЗапроса 		- Структура - содержит перечисления полей для выполнения запроса
//  HTTPМетод 				- Строка - содержит метод вызова GET, POST и прочие варианты
//  ТипСодержания			- Строка - указывает как формировать тело запроса из ПараметрыМетода, поддерживаются варианты:
//								octet: передать двоичными данными,
//								text: передать структуру как форматированную строку,
//								json_list: передать как json и вернуть как Соответствие,
//								json: передать как json.
//  ПараметрыОперации		- Неопределено, Структура
//
// Возвращаемое значение:
//   см. СервисКриптографииDSSКлиентСервер.ОтветСервисаПоУмолчанию
//
Функция ВыполнитьЗапросКСервису(НастройкиПользователя, АдресПодключения, ПараметрыЗапроса, HTTPМетод, ТипСодержания, ПараметрыОперации = Неопределено) Экспорт
	
	Заголовки			= Новый Соответствие;
	СекретПользователя 	= ПолучитьПредставлениеСекрета(НастройкиПользователя, ПолучитьЗначениеПароля(НастройкиПользователя.Пароль, НастройкиПользователя));
	Заголовки.Вставить("Authorization", СекретПользователя);
	
	СвойстваПодключения	= СервисКриптографииDSSСлужебный.ПодготовитьСвойстваПодключения(НастройкиПользователя.Подключение, АдресПодключения);
	Соединение			= СервисКриптографииDSSСлужебный.ПодготовитьПодключение(СвойстваПодключения, Неопределено, ПараметрыОперации);
	РезультатЗапроса	= СервисКриптографииDSSСлужебный.ВыполнитьМетодСервиса(Соединение, 
					СвойстваПодключения.АдресПодключения, 
					ПараметрыЗапроса, 
					HTTPМетод, 
					Заголовки, 
					ТипСодержания,
					ПараметрыОперации);

	СервисКриптографииDSSСлужебный.ПротоколОшибкиПриВызове(РезультатЗапроса, "ВыполнитьЗапросКСервису", ПараметрыЗапроса, , ПараметрыОперации);
	
	Возврат РезультатЗапроса;
	
КонецФункции

// Получает выборку записей аудита (действий пользователя) на сервере
//
// Параметры:
//  ИдентификаторПользователя 	- Структура, СправочникСсылка.УчетныеЗаписиDSS - см. функцию НастройкиПользователяПоУмолчанию()
//  ФильтрыОтбора 				- Массив из Структура, Неопределено - если передан массив, то каждый элемент это структура с полями:
//    * Колонка 				- Число, Неопределено - колонка в БД, по которой осуществляется фильтрация
//    * Операция 				- Число, Неопределено - операция, которая применяется фильтром
//    * Значение 				- Строка, Неопределено - значение фильтра
//  НачальнаяПозиция			- Неопределено, Число - если не задано, то Значение по умолчанию - 0
//  КонечнаяПозиция				- Неопределено, Число - если не задано, то Значение по умолчанию - 10 к начальной позиции
//  ПараметрыОперации 			- Структура, ФиксированнаяСтруктура - позволяет указать дополнительные параметры операции.
//
// Возвращаемое значение:
//   см. СервисКриптографииDSSКлиентСервер.ОтветСервисаПоУмолчанию
//
Функция ПолучитьЗаписиАудита(ИдентификаторПользователя, 
					ФильтрыОтбора,
					НачальнаяПозиция = Неопределено, 
					КонечнаяПозиция = Неопределено,
					ПараметрыОперации = Неопределено) Экспорт
					
	
	НастройкиПользователя	= ПолучитьНастройкиПользователя(ИдентификаторПользователя, ПараметрыОперации);
	РезультатЗапроса		= СервисКриптографииDSSКлиентСервер.ПроверитьВерсиюСервера(НастройкиПользователя, "2");
	
	Если РезультатЗапроса.Выполнено Тогда
		АдресПодключения = НастройкиПользователя.Методы.СервисАудита + "audit";
		
		ПараметрыЗапроса = Новый Структура;
		Если ЗначениеЗаполнено(НачальнаяПозиция) Тогда
			ПараметрыЗапроса.Вставить("StartPosition", НачальнаяПозиция);
		Иначе
			ПараметрыЗапроса.Вставить("StartPosition", 0);
		КонецЕсли;	
		
		Если ЗначениеЗаполнено(КонечнаяПозиция) Тогда
			ПараметрыЗапроса.Вставить("EndPosition", КонечнаяПозиция);
		Иначе
			ПараметрыЗапроса.Вставить("EndPosition", ПараметрыЗапроса.StartPosition + 10);
		КонецЕсли;	
		
		Если ФильтрыОтбора <> Неопределено Тогда
			
			МассивФильтров = Новый Массив;
			
			Для Каждого СтрокаМассива Из ФильтрыОтбора Цикл
				НоваяСтрока = Новый Структура;
				НоваяСтрока.Вставить("Column", СтрокаМассива.Колонка);
				НоваяСтрока.Вставить("Operation", СтрокаМассива.Операция);
				НоваяСтрока.Вставить("FilterValue", СтрокаМассива.Значение);
				МассивФильтров.Добавить(НоваяСтрока);
			КонецЦикла;
			
			Если МассивФильтров.Количество() > 0 Тогда
				ПараметрыЗапроса.Вставить("Filters", МассивФильтров);
			КонецЕсли;	
			
		КонецЕсли;
		
		РезультатЗапроса = ПодключитьВыполнитьМетодСервиса(НастройкиПользователя, АдресПодключения, ПараметрыЗапроса, "POST", "json", , ПараметрыОперации);
		
		Если РезультатЗапроса.Выполнено Тогда
			МассивЗаписей = Новый Массив;
			
			РезультатЗапроса.Вставить("ЧислитсяЗаписей", СвойствоСтруктуры(РезультатЗапроса.Результат, "TotalCount", 0));
			ПолученныеЗаписи = СвойствоСтруктуры(РезультатЗапроса.Результат, "records", Новый Массив);
			
			Для Каждого СтрокаМассива Из ПолученныеЗаписи Цикл
				НоваяСтрока = Новый Структура;
				
				НоваяСтрока.Вставить("Идентификатор", СтрокаМассива.ID);
				НоваяСтрока.Вставить("КодСобытия", СтрокаМассива.EventCode);
				НоваяСтрока.Вставить("ИсточникСобытия", СтрокаМассива.EventSource);
				НоваяСтрока.Вставить("ИсточникСобытияИнфо", СтрокаМассива.SourceDetails);
				НоваяСтрока.Вставить("Описание", СтрокаМассива.Data);
				НоваяСтрока.Вставить("Пользователь", СтрокаМассива.Login);
				НоваяСтрока.Вставить("ИмяДоверенногоИздателя", СтрокаМассива.Realm);
				НоваяСтрока.Вставить("Дата", СтрокаМассива.Date);
				НоваяСтрока.Вставить("ДанныеСобытия", СтрокаМассива.ExtendedData);
				НоваяСтрока.Вставить("Оператор", СтрокаМассива.DelegatedUserLogin);
				НоваяСтрока.Вставить("УровеньСобытия", СтрокаМассива.EventLevel);
				
				МассивЗаписей.Добавить(НоваяСтрока);
				
			КонецЦикла;	
			
			РезультатЗапроса.Вставить("Результат", МассивЗаписей);
		КонецЕсли;
		
	КонецЕсли;
	
	СервисКриптографииDSSСлужебный.ПротоколОшибкиПриВызове(РезультатЗапроса, "ЗапросЗаписейАудита", ПараметрыЗапроса, , ПараметрыОперации);
	
	Возврат РезультатЗапроса;
	
					
КонецФункции

// Формируется данные об учетной записи в формате XML на основании отчета "Состояние учетной записи"
//
// Параметры:
//  НастройкиПользователя 	- Структура, СправочникСсылка.УчетныеЗаписиDSS - см. функцию НастройкиПользователяПоУмолчанию()
//  ПараметрыОперации 		- Структура, ФиксированнаяСтруктура - позволяет указать дополнительные параметры операции.
//
// Возвращаемое значение:
//   см. СервисКриптографииDSSКлиентСервер.ОтветСервисаПоУмолчанию
//
Функция СостояниеУчетнойЗаписи(НастройкиПользователя, ПараметрыОперации = Неопределено) Экспорт
	
	Результат = СервисКриптографииDSSКлиентСервер.ОтветСервисаПоУмолчанию();
	ОбъектОтчета = Отчеты.СостояниеУчетнойЗаписиDSS.Создать();
	Если ОбъектОтчета <> Неопределено Тогда
		ПараметрыОтчета = ОбъектОтчета.КомпоновщикНастроек.Настройки.ПараметрыДанных;
		ПараметрыОтчета.УстановитьЗначениеПараметра("НастройкиПользователя", НастройкиПользователя);
		ПараметрыОтчета.УстановитьЗначениеПараметра("ФорматРезультата", "XML");
		ДанныеОтчета = ОбъектОтчета.СформироватьДанныеОтчета(Неопределено);
		Результат.Вставить("Результат", ДанныеОтчета);
	Иначе
		Результат.Выполнено = Ложь;
		Результат.Ошибка = НСтр("ru = 'Не удалось сформировать отчет'", СервисКриптографииDSSСлужебный.КодЯзыка());
	КонецЕсли;	
		
	Возврат Результат;
	
КонецФункции

#КонецОбласти

#Область ОбработкаДокументов

// Отправляет документ на сервер, для последующей обработки.
//
// Параметры:
//  ИдентификаторПользователя 	- Структура, СправочникСсылка.УчетныеЗаписиDSS - см. функцию НастройкиПользователяПоУмолчанию()
//  ДанныеДокумента 			- ДвоичныеДанные, Строка - один файл, который необходимо обработать,
//								подробнее СервисКриптографииDSSКлиентСервер.ПодготовитьДанныеДокумента().
//  ПараметрыДокумента			- см. СервисКриптографииDSSКлиентСервер.ПолучитьСвойстваДокумента
//  ПараметрыОперации 			- Структура, ФиксированнаяСтруктура - позволяет указать дополнительные параметры операции. 
//
// Возвращаемое значение:
//   см. СервисКриптографииDSSКлиентСервер.ОтветСервисаПоУмолчанию
//
Функция ЗагрузитьДокумент(ИдентификаторПользователя, 
							ДанныеДокумента, 
							ПараметрыДокумента, 
							ПараметрыОперации = Неопределено) Экспорт
							
							
	НастройкиПользователя	= ПолучитьНастройкиПользователя(ИдентификаторПользователя, ПараметрыОперации);
	РезультатЗапроса		= СервисКриптографииDSSКлиентСервер.ПроверитьВерсиюСервера(НастройкиПользователя, "2");
	
	Если РезультатЗапроса.Выполнено Тогда
		
		СтруктураДокумента		= СервисКриптографииDSSКлиентСервер.ПодготовитьДанныеДокумента(ДанныеДокумента, Истина);
		ПодготовленныеДанные	= СтруктураДокумента.Документ;
		АдресПодключения 		= НастройкиПользователя.Методы.СервисДокументов;
		ПредставлениеЗаголовка	= СервисКриптографииDSSСлужебный.ПодготовитьЗаголовокПотока(ПараметрыДокумента);
		
		Заголовки				= Новый Соответствие;
		Заголовки.Вставить("CPDSS-POSTDOC", ПредставлениеЗаголовка);
		Заголовки.Вставить("Content-Type", "application/octet-stream");
		
		РезультатЗапроса	= ПодключитьВыполнитьМетодСервиса(НастройкиПользователя, АдресПодключения, ПодготовленныеДанные, "POST", "octet", Заголовки, ПараметрыОперации);
		Если РезультатЗапроса.Выполнено Тогда
			РезультатЗапроса.Результат = СвойствоСтруктуры(РезультатЗапроса.Результат, "DocumentId", "");
		КонецЕсли;	
		
	КонецЕсли;
	
	СервисКриптографииDSSСлужебный.ПротоколОшибкиПриВызове(РезультатЗапроса, "ЗагрузитьДокумент", ПараметрыДокумента, , ПараметрыОперации);
		
	Возврат РезультатЗапроса;
							
КонецФункции	

// Отправляет пакет (небольшой) документов (небольших) на сервер, для последующей обработки.
//
// Параметры:
//  ИдентификаторПользователя 	- Структура, СправочникСсылка.УчетныеЗаписиDSS - см. функцию НастройкиПользователяПоУмолчанию()
//  ПараметрыДокументов			- Массив из см. СервисКриптографииDSSКлиентСервер.ПолучитьСвойстваДокумента
//  ПараметрыОперации 			- Структура, ФиксированнаяСтруктура - позволяет указать дополнительные параметры операции. 
//
// Возвращаемое значение:
//   см. СервисКриптографииDSSКлиентСервер.ОтветСервисаПоУмолчанию
//
Функция ЗагрузитьПакетДокументов(ИдентификаторПользователя, 
							ПараметрыДокументов,
							ПараметрыОперации = Неопределено) Экспорт
							
							
	НастройкиПользователя	= ПолучитьНастройкиПользователя(ИдентификаторПользователя, ПараметрыОперации);
	РезультатЗапроса		= СервисКриптографииDSSКлиентСервер.ПроверитьВерсиюСервера(НастройкиПользователя, "2");
	ПараметрыЗапроса		= Новый Структура;
	
	Если РезультатЗапроса.Выполнено Тогда
		
		АдресПодключения 		= НастройкиПользователя.Методы.СервисДокументов + "/pack";
		Заголовки				= Новый Соответствие;
		ПараметрыЗапроса.Вставить("Documents", ПараметрыДокументов);
		
		РезультатЗапроса	= ПодключитьВыполнитьМетодСервиса(НастройкиПользователя, АдресПодключения, ПараметрыЗапроса, "POST", "json", Заголовки, ПараметрыОперации);
		Если РезультатЗапроса.Выполнено Тогда
			РезультатЗапроса.Результат = СвойствоСтруктуры(РезультатЗапроса.Результат, "DocumentIds", Новый Массив);
		КонецЕсли;	
		
	КонецЕсли;
	
	СервисКриптографииDSSСлужебный.ПротоколОшибкиПриВызове(РезультатЗапроса, "ЗагрузитьПакетДокументов", ПараметрыДокументов, , ПараметрыОперации);
		
	Возврат РезультатЗапроса;
							
КонецФункции

// Возвращает информацию о загруженном на сервер документе по его идентификатору.
//
// Параметры:
//  ИдентификаторПользователя 	- Структура, СправочникСсылка.УчетныеЗаписиDSS - см. функцию НастройкиПользователяПоУмолчанию()
//  ИдентификаторДокумента 		- Строка - идентификатор документа, присвоенный при его загрузке
//  ПараметрыОперации 			- Структура, ФиксированнаяСтруктура - позволяет указать дополнительные параметры операции. 
//
// Возвращаемое значение:
//   см. СервисКриптографииDSSКлиентСервер.ОтветСервисаПоУмолчанию
//
Функция ИнформацияОДокументеПоИдентификатору(ИдентификаторПользователя, 
							ИдентификаторДокумента,
							ПараметрыОперации = Неопределено) Экспорт
							
	НастройкиПользователя	= ПолучитьНастройкиПользователя(ИдентификаторПользователя, ПараметрыОперации);
	РезультатЗапроса		= СервисКриптографииDSSКлиентСервер.ПроверитьВерсиюСервера(НастройкиПользователя, "2");
	
	Если РезультатЗапроса.Выполнено Тогда
		
		АдресПодключения 		= НастройкиПользователя.Методы.СервисДокументов + "/%1/info";
		АдресПодключения		= ЗаполнитьПараметрыСтроки(АдресПодключения, ИдентификаторДокумента);
		Заголовки				= Новый Соответствие;
		
		РезультатЗапроса	= ПодключитьВыполнитьМетодСервиса(НастройкиПользователя, АдресПодключения, Неопределено, "GET", "json", Заголовки, ПараметрыОперации);
		Если РезультатЗапроса.Выполнено Тогда
			РезультатЗапроса.Результат = ИнформацияОДокументеОбработки(РезультатЗапроса.Результат);
		КонецЕсли;	
		
	КонецЕсли;
	
	СервисКриптографииDSSСлужебный.ПротоколОшибкиПриВызове(РезультатЗапроса, "ИнформацияОДокументеПоИдентификатору", ИдентификаторДокумента, , ПараметрыОперации);
		
	Возврат РезультатЗапроса;
							
КонецФункции

// Возвращает информацию о загруженном на сервер документе по его хешу.
//
// Параметры:
//  ИдентификаторПользователя 	- Структура, СправочникСсылка.УчетныеЗаписиDSS - см. функцию НастройкиПользователяПоУмолчанию()
//  ХешДокумента 				- Строка - хеш документа, вычисленный при его загрузке на сервер
//  ПараметрыОперации 			- Структура, ФиксированнаяСтруктура - позволяет указать дополнительные параметры операции. 
//
// Возвращаемое значение:
//   см. СервисКриптографииDSSКлиентСервер.ОтветСервисаПоУмолчанию
//
Функция ИнформацияОДокументеПоХешу(ИдентификаторПользователя, 
							ХешДокумента,
							ПараметрыОперации = Неопределено) Экспорт
							
	НастройкиПользователя	= ПолучитьНастройкиПользователя(ИдентификаторПользователя, ПараметрыОперации);
	РезультатЗапроса		= СервисКриптографииDSSКлиентСервер.ПроверитьВерсиюСервера(НастройкиПользователя, "2");
	
	Если РезультатЗапроса.Выполнено Тогда
		
		АдресПодключения 		= НастройкиПользователя.Методы.СервисДокументов + "/hash/%1/info";
		АдресПодключения		= ЗаполнитьПараметрыСтроки(АдресПодключения, ХешДокумента);
		Заголовки				= Новый Соответствие;
		
		РезультатЗапроса	= ПодключитьВыполнитьМетодСервиса(НастройкиПользователя, АдресПодключения, Неопределено, "GET", "json", Заголовки, ПараметрыОперации);
		Если РезультатЗапроса.Выполнено Тогда
			РезультатЗапроса.Результат = ИнформацияОДокументеОбработки(РезультатЗапроса.Результат);
		КонецЕсли;	
		
	КонецЕсли;
	
	СервисКриптографииDSSСлужебный.ПротоколОшибкиПриВызове(РезультатЗапроса, "ИнформацияОДокументеПоИдентификатору", ХешДокумента, , ПараметрыОперации);
		
	Возврат РезультатЗапроса;
							
КонецФункции

// Получить документ с сервера. Это может быть как ранее отправленный документ (см. ЗагрузитьДокумент), 
// так и обработанный документ.
//
// Параметры:
//  ИдентификаторПользователя 	- Структура, СправочникСсылка.УчетныеЗаписиDSS - см. функцию НастройкиПользователяПоУмолчанию()
//  ИдентификаторДокумента		- Строка
//  ПараметрыОперации 			- Структура, ФиксированнаяСтруктура - позволяет указать дополнительные параметры операции. 
//
// Возвращаемое значение:
//   см. СервисКриптографииDSSКлиентСервер.ОтветСервисаПоУмолчанию
//
Функция ПолучитьОбработанныйДокумент(ИдентификаторПользователя, 
							ИдентификаторДокумента, 
							ПараметрыОперации = Неопределено) Экспорт
							
	НастройкиПользователя	= ПолучитьНастройкиПользователя(ИдентификаторПользователя, ПараметрыОперации);
	РезультатЗапроса		= СервисКриптографииDSSКлиентСервер.ПроверитьВерсиюСервера(НастройкиПользователя, "2");
	
	Если РезультатЗапроса.Выполнено Тогда
		
		АдресПодключения 		= НастройкиПользователя.Методы.СервисДокументов + "/%1/content";
		АдресПодключения		= ЗаполнитьПараметрыСтроки(АдресПодключения, ИдентификаторДокумента);
		Заголовки				= Новый Соответствие;
		
		РезультатЗапроса	= ПодключитьВыполнитьМетодСервиса(НастройкиПользователя, АдресПодключения, Неопределено, "GET", "json", Заголовки, ПараметрыОперации);
		
	КонецЕсли;
	
	СервисКриптографииDSSСлужебный.ПротоколОшибкиПриВызове(РезультатЗапроса, "ПолучитьОбработанныйДокумент", ИдентификаторДокумента, , ПараметрыОперации);
		
	Возврат РезультатЗапроса;
							
КонецФункции	

// Получить документы с сервера. Это может быть как ранее отправленные документы (см. ЗагрузитьДокумент), 
// так и обработанные документы. Используется API версии 2.0.
//
// Параметры:
//  ИдентификаторПользователя 	- Структура, СправочникСсылка.УчетныеЗаписиDSS - см. функцию НастройкиПользователяПоУмолчанию()
//  ИдентификаторыДокументов	- Строка
//                          	- Массив
//  ПараметрыОперации 			- Структура, ФиксированнаяСтруктура - позволяет указать дополнительные параметры операции:
//    * МультиЧасти			- Булево
//
// Возвращаемое значение:
//   см. СервисКриптографииDSSКлиентСервер.ОтветСервисаПоУмолчанию
//
Функция ПолучитьОбработанныеДокументы(ИдентификаторПользователя, 
							ИдентификаторыДокументов, 
							ПараметрыОперации = Неопределено) Экспорт
							
	НастройкиПользователя	= ПолучитьНастройкиПользователя(ИдентификаторПользователя, ПараметрыОперации);
	РезультатЗапроса		= СервисКриптографииDSSКлиентСервер.ПроверитьВерсиюСервера(НастройкиПользователя, "2");
	МультиЧасти				= СвойствоСтруктуры(ПараметрыОперации, "МультиЧасти", Истина);
	МассивИдентификаторов 	= СервисКриптографииDSSКлиентСервер.ЗначениеВМассиве(ИдентификаторыДокументов);
	РеестрДокументов		= Новый Соответствие;
	
	Если РезультатЗапроса.Выполнено Тогда
		
		Заголовки			= Новый Соответствие;
		ПараметрыЗапроса	= Новый Структура;
		
		Если МультиЧасти Тогда
			АдресПодключения 	= НастройкиПользователя.Методы.СервисДокументов + "/content/download";
			ПараметрыЗапроса.Вставить("DocumentIds", МассивИдентификаторов);
			РезультатЗапроса	= ПодключитьВыполнитьМетодСервиса(НастройкиПользователя, АдресПодключения, ПараметрыЗапроса, "POST", "json", Заголовки, ПараметрыОперации);
			
			Если РезультатЗапроса.Выполнено Тогда
				Для Каждого СтрокаМассива Из РезультатЗапроса.Результат Цикл
					ОписаниеДокумента = СвойствоСтруктуры(СтрокаМассива.ЗаголовкиРаздела, "Content-Disposition", "");
					ТипСодержимого = СвойствоСтруктуры(СтрокаМассива.ЗаголовкиРаздела, "Content-Type", "");
					
					Если СтрНайти(ТипСодержимого, "application/json") > 0 Тогда
						РезультатЗапроса.Выполнено = Ложь;
						ОписаниеОшибки = СервисКриптографииDSSСлужебный.ИзвлечьОписаниеОшибки(ТипСодержимого, СтрокаМассива.Содержимое);
						СервисКриптографииDSSСлужебный.ПолучитьОписаниеОшибки(РезультатЗапроса, ОписаниеОшибки.Ошибка, ОписаниеОшибки.Сообщение);
						Прервать;
					КонецЕсли;
					
					Если НЕ ЗначениеЗаполнено(ОписаниеДокумента) Тогда
						Продолжить;
					КонецЕсли;
					
					ИдентификаторДокумента = "";
					ВсеПараметры = СтрРазделить(ОписаниеДокумента, ";", Ложь);
					Для Каждого СтрокаПараметра Из ВсеПараметры Цикл
						Позиция = СтрНайти(СтрокаПараметра, "name=");
						Если Позиция > 0 Тогда
							ИдентификаторДокумента = Сред(СтрокаПараметра, Позиция + 5);
						КонецЕсли;
					КонецЦикла;
					
					Если ЗначениеЗаполнено(ИдентификаторДокумента) Тогда
						РеестрДокументов.Вставить(ИдентификаторДокумента, СтрокаМассива.Содержимое);
					КонецЕсли;
					
				КонецЦикла;
				
			КонецЕсли;
			
			Если МассивИдентификаторов.Количество() <> РеестрДокументов.Количество() Тогда
				РезультатЗапроса = СервисКриптографииDSSКлиентСервер.ОтветСервисаПоУмолчанию(Ложь);
				СервисКриптографииDSSСлужебный.ПолучитьОписаниеОшибки(РезультатЗапроса, "ОшибкаВыполнения");
			КонецЕсли;
			
		Иначе
			
			Для Каждого СтрокаМассива Из МассивИдентификаторов Цикл
				РезультатЗапроса = ПолучитьОбработанныйДокумент(НастройкиПользователя, СтрокаМассива, ПараметрыОперации);
				Если НЕ РезультатЗапроса.Выполнено Тогда
					Прервать;
				Иначе
					РеестрДокументов.Вставить(СтрокаМассива, РезультатЗапроса.Результат);
				КонецЕсли;
			КонецЦикла;
			
		КонецЕсли;
		
	КонецЕсли;
	
	Если РезультатЗапроса.Выполнено Тогда
		СписокДокументов = Новый Массив;
		Для Счетчик = 0 По МассивИдентификаторов.Количество() - 1 Цикл
			СписокДокументов.Добавить(Base64Строка(РеестрДокументов[МассивИдентификаторов[Счетчик]]));
		КонецЦикла;
		РезультатЗапроса.Результат = СписокДокументов;
	КонецЕсли;
	
	СервисКриптографииDSSСлужебный.ПротоколОшибкиПриВызове(РезультатЗапроса, "ПолучитьОбработанныйДокумент", ИдентификаторыДокументов, , ПараметрыОперации);
		
	Возврат РезультатЗапроса;
							
КонецФункции	

// Изменяет информацию о ранее загруженном документе на сервере.
//
// Параметры:
//  ИдентификаторПользователя 	- СправочникСсылка.УчетныеЗаписиDSS
//                            	- Структура - см. НастройкиПользователяПоУмолчанию()
//  ИдентификаторДокумента		- Строка
//  ПараметрыДокумента			- Структура - подробнее ИнформацияОДокументеОбработки
//  ПараметрыОперации 			- Структура, ФиксированнаяСтруктура - позволяет указать дополнительные параметры операции. 
//
// Возвращаемое значение:
//   см. СервисКриптографииDSSКлиентСервер.ОтветСервисаПоУмолчанию
//
Функция ИзменитьИнформациюОДокументе(ИдентификаторПользователя, 
							ИдентификаторДокумента,
							ПараметрыДокумента,
							ПараметрыОперации = Неопределено) Экспорт
							
	НастройкиПользователя	= ПолучитьНастройкиПользователя(ИдентификаторПользователя, ПараметрыОперации);
	РезультатЗапроса		= СервисКриптографииDSSКлиентСервер.ПроверитьВерсиюСервера(НастройкиПользователя, "2");
	
	Если РезультатЗапроса.Выполнено Тогда
		
		АдресПодключения 		= НастройкиПользователя.Методы.СервисДокументов + "/%1";
		АдресПодключения		= ЗаполнитьПараметрыСтроки(АдресПодключения, ИдентификаторДокумента);
		Заголовки				= Новый Соответствие;
		
		РезультатЗапроса	= ПодключитьВыполнитьМетодСервиса(НастройкиПользователя, АдресПодключения, ПараметрыДокумента, "PATCH", "json", Заголовки, ПараметрыОперации);
		
	КонецЕсли;
	
	СервисКриптографииDSSСлужебный.ПротоколОшибкиПриВызове(РезультатЗапроса, "ИзменитьИнформациюОДокументе", ПараметрыДокумента, , ПараметрыОперации);
		
	Возврат РезультатЗапроса;
							
КонецФункции

// Привязывает текущий документ к указанному.
//
// Параметры:
//  ИдентификаторПользователя 	- Структура, СправочникСсылка.УчетныеЗаписиDSS - см. функцию НастройкиПользователяПоУмолчанию()
//  ИдентификаторДокумента 		- Строка
//  ИдентификаторРодительскогоДокумента	- Строка
//  ПараметрыОперации 			- Структура, ФиксированнаяСтруктура - позволяет указать дополнительные параметры операции. 
//
// Возвращаемое значение:
//   см. СервисКриптографииDSSКлиентСервер.ОтветСервисаПоУмолчанию
//
Функция ПривязатьДокумент(ИдентификаторПользователя, 
							ИдентификаторДокумента,
							ИдентификаторРодительскогоДокумента,
							ПараметрыОперации = Неопределено) Экспорт
							
	НастройкиПользователя	= ПолучитьНастройкиПользователя(ИдентификаторПользователя, ПараметрыОперации);
	РезультатЗапроса		= СервисКриптографииDSSКлиентСервер.ПроверитьВерсиюСервера(НастройкиПользователя, "2");
	ПараметрыЗапроса		= Новый Структура;
	
	Если РезультатЗапроса.Выполнено Тогда
		
		АдресПодключения 		= НастройкиПользователя.Методы.СервисДокументов + "/%1/link";
		АдресПодключения		= ЗаполнитьПараметрыСтроки(АдресПодключения, ИдентификаторДокумента);
		Заголовки				= Новый Соответствие;
		ПараметрыЗапроса.Вставить("DocumentId", ИдентификаторРодительскогоДокумента);
		
		РезультатЗапроса	= ПодключитьВыполнитьМетодСервиса(НастройкиПользователя, АдресПодключения, ПараметрыЗапроса, "POST", "json", Заголовки, ПараметрыОперации);
		
	КонецЕсли;
	
	СервисКриптографииDSSСлужебный.ПротоколОшибкиПриВызове(РезультатЗапроса, "ПривязатьДокумент", ПараметрыЗапроса, , ПараметрыОперации);
		
	Возврат РезультатЗапроса;
							
КонецФункции

// Посылает запрос на конвертацию документа, ранее загруженного на сервер.
//
// Параметры:
//  ИдентификаторПользователя 	- Структура, СправочникСсылка.УчетныеЗаписиDSS - см. функцию НастройкиПользователяПоУмолчанию()
//  ИдентификаторДокумента 		- Строка
//  ПараметрыОперации 			- Структура, ФиксированнаяСтруктура - позволяет указать дополнительные параметры операции. 
//
// Возвращаемое значение:
//   см. СервисКриптографииDSSКлиентСервер.ОтветСервисаПоУмолчанию
//
Функция СконвертироватьДокумент(ИдентификаторПользователя, 
							ИдентификаторДокумента,
							ПараметрыОперации = Неопределено) Экспорт
							
	НастройкиПользователя	= ПолучитьНастройкиПользователя(ИдентификаторПользователя, ПараметрыОперации);
	РезультатЗапроса		= СервисКриптографииDSSКлиентСервер.ПроверитьВерсиюСервера(НастройкиПользователя, "2");
	
	Если РезультатЗапроса.Выполнено Тогда
		
		АдресПодключения 	= НастройкиПользователя.Методы.СервисДокументов + "/%1/converted_content";
		АдресПодключения	= ЗаполнитьПараметрыСтроки(АдресПодключения, ИдентификаторДокумента);
		Заголовки			= Новый Соответствие;
		РезультатЗапроса	= ПодключитьВыполнитьМетодСервиса(НастройкиПользователя, АдресПодключения, Неопределено, "POST", "json", Заголовки, ПараметрыОперации);
		
	КонецЕсли;
	
	Если РезультатЗапроса.Выполнено Тогда
		СостояниеДокумента = ИнформацияОКонвертацииДокумента(РезультатЗапроса.Результат);
		
		Если СостояниеДокумента.Статус = "Ошибка" Тогда
			РезультатЗапроса.Выполнено = Ложь;
			СервисКриптографииDSSСлужебный.ПолучитьОписаниеОшибки(РезультатЗапроса, "ОшибкаКонвертации", СостояниеДокумента.Описание);
		КонецЕсли;
		
		РезультатЗапроса.Результат = СостояниеДокумента;
		
	КонецЕсли;
	
	СервисКриптографииDSSСлужебный.ПротоколОшибкиПриВызове(РезультатЗапроса, "СконвертироватьДокумент", ИдентификаторПользователя, , ПараметрыОперации);
		
	Возврат РезультатЗапроса;
							
КонецФункции

// Получает информацию о преобразованном документе.
//
// Параметры:
//  ИдентификаторПользователя 	- Структура, СправочникСсылка.УчетныеЗаписиDSS - см. функцию НастройкиПользователяПоУмолчанию()
//  ИдентификаторДокумента 		- Строка
//  ПараметрыОперации 			- Структура, ФиксированнаяСтруктура - позволяет указать дополнительные параметры операции. 
//
// Возвращаемое значение:
//   см. СервисКриптографииDSSКлиентСервер.ОтветСервисаПоУмолчанию
//
Функция ПолучитьИнформациюДокументаКонвертации(ИдентификаторПользователя, 
							ИдентификаторДокумента,
							ПараметрыОперации = Неопределено) Экспорт
							
	НастройкиПользователя	= ПолучитьНастройкиПользователя(ИдентификаторПользователя, ПараметрыОперации);
	РезультатЗапроса		= СервисКриптографииDSSКлиентСервер.ПроверитьВерсиюСервера(НастройкиПользователя, "2");
	
	Если РезультатЗапроса.Выполнено Тогда
		
		АдресПодключения 	= НастройкиПользователя.Методы.СервисДокументов + "/%1/converted_content/info";
		АдресПодключения	= ЗаполнитьПараметрыСтроки(АдресПодключения, ИдентификаторДокумента);
		Заголовки			= Новый Соответствие;
		РезультатЗапроса	= ПодключитьВыполнитьМетодСервиса(НастройкиПользователя, АдресПодключения, Неопределено, "GET", "json", Заголовки, ПараметрыОперации);
		
	КонецЕсли;
	
	Если РезультатЗапроса.Выполнено Тогда
		
		СостояниеДокумента = ИнформацияОКонвертацииДокумента(РезультатЗапроса.Результат);
		
		Если СостояниеДокумента.Статус = "Ошибка" Тогда
			РезультатЗапроса.Выполнено = Ложь;
			СервисКриптографииDSSСлужебный.ПолучитьОписаниеОшибки(РезультатЗапроса, "ОшибкаКонвертации", СостояниеДокумента.Описание);
		КонецЕсли;
		
		РезультатЗапроса.Результат = СостояниеДокумента;
		
	КонецЕсли;
	
	СервисКриптографииDSSСлужебный.ПротоколОшибкиПриВызове(РезультатЗапроса, "ПолучитьИнформациюДокументаКонвертации", ИдентификаторПользователя, , ПараметрыОперации);
		
	Возврат РезультатЗапроса;
							
КонецФункции

// Удаляет документ ранее загруженный на сервер или обработанный на нем.
//
// Параметры:
//  ИдентификаторПользователя 	- СправочникСсылка.УчетныеЗаписиDSS
//                            	- Структура - см. функцию НастройкиПользователяПоУмолчанию()
//  ИдентификаторДокумента		- Строка
//  ПараметрыДокумента			- Структура - подробнее ИнформацияОДокументеОбработки
//  ПараметрыОперации 			- Структура, ФиксированнаяСтруктура - позволяет указать дополнительные параметры операции. 
//
// Возвращаемое значение:
//   см. СервисКриптографииDSSКлиентСервер.ОтветСервисаПоУмолчанию
//
Функция УдалитьДокумент(ИдентификаторПользователя, 
							ИдентификаторДокумента,
							ПараметрыДокумента,
							ПараметрыОперации = Неопределено) Экспорт
							
	НастройкиПользователя	= ПолучитьНастройкиПользователя(ИдентификаторПользователя, ПараметрыОперации);
	РезультатЗапроса		= СервисКриптографииDSSКлиентСервер.ПроверитьВерсиюСервера(НастройкиПользователя, "2");
	
	Если РезультатЗапроса.Выполнено Тогда
		
		АдресПодключения 	= НастройкиПользователя.Методы.СервисДокументов + "/%1";
		АдресПодключения	= ЗаполнитьПараметрыСтроки(АдресПодключения, ИдентификаторДокумента);
		Заголовки				= Новый Соответствие;
		
		РезультатЗапроса	= ПодключитьВыполнитьМетодСервиса(НастройкиПользователя, АдресПодключения, ПараметрыДокумента, "DELETE", "json", Заголовки, ПараметрыОперации);
		
	КонецЕсли;
	
	СервисКриптографииDSSСлужебный.ПротоколОшибкиПриВызове(РезультатЗапроса, "УдалитьДокумент", ПараметрыДокумента, , ПараметрыОперации);
		
	Возврат РезультатЗапроса;
							
КонецФункции

#КонецОбласти

#Область ЗакрытыеКлючи

// Создает закрытый ключ и сертификат к нему на сервере, подписанный владельцем.
//
// Параметры:
//  ИдентификаторПользователя 	- Структура, СправочникСсылка.УчетныеЗаписиDSS - см. функцию НастройкиПользователяПоУмолчанию()
//  ИдентификаторАлгоритмаКлюча	- Строка - идентификатор алгоритма закрытого ключа, подробности см. подробности см. СервисКриптографииDSSКлиентСервер.ИдентификаторАлгоритмаЗакрытогоКлюча
//  ПараметрыКлюча 				- Строка - идентификатор набора параметров эллиптической кривой 
//  ПинКод 						- Строка - пин-код для доступа к вновь создаваемому ключу
//  ПараметрыОперации 			- Структура, ФиксированнаяСтруктура - позволяет указать дополнительные параметры операции. Проверяемые поля:
//			
// Возвращаемое значение:
//   см. СервисКриптографииDSSКлиентСервер.ОтветСервисаПоУмолчанию
//
Функция СоздатьЗакрытыйКлюч(ИдентификаторПользователя, 
					ИдентификаторАлгоритмаКлюча, 
					ПараметрыКлюча, 
					ПинКод = "", 
					ПараметрыОперации = Неопределено) Экспорт
	
	НастройкиПользователя	= ПолучитьНастройкиПользователя(ИдентификаторПользователя, ПараметрыОперации);
	РезультатЗапроса		= СервисКриптографииDSSКлиентСервер.ПроверитьВерсиюСервера(НастройкиПользователя, "2");
	ЗначениеПинКода			= ПолучитьЗначениеПароля(ПинКод, НастройкиПользователя);
	
	Если РезультатЗапроса.Выполнено Тогда
		ПараметрыЗапроса		= Новый Структура;
		Если ЗначениеЗаполнено(ЗначениеПинКода) Тогда
			ПараметрыЗапроса.Вставить("PinCode", ЗначениеПинКода);
		КонецЕсли;
		
		Если ЗначениеЗаполнено(ПараметрыКлюча) Тогда
			ПараметрыЗапроса.Вставить("ParametersOid", ПараметрыКлюча);
		Иначе
			ПараметрыЗапроса.Вставить("ParametersOid", "");
		КонецЕсли;
		
		ПараметрыЗапроса.Вставить("AlgId", ИдентификаторАлгоритмаКлюча);
		
		АдресПодключения	= НастройкиПользователя.Методы.СервисПодписи + "keys/generate";
		РезультатЗапроса	= ПодключитьВыполнитьМетодСервиса(НастройкиПользователя, АдресПодключения, ПараметрыЗапроса, "POST", "json", , ПараметрыОперации);
		Если РезультатЗапроса.Выполнено Тогда
			Если НЕ СвойствоСтруктуры(РезультатЗапроса.Результат, "IsError", Ложь) Тогда
				ДанныеСертификата = СвойствоСтруктуры(РезультатЗапроса.Результат, "CertificateBase64", "");
				ИнформацияКлюча = Новый Структура;
				ИнформацияКлюча.Вставить("ИдентификаторСертификата", СвойствоСтруктуры(РезультатЗапроса.Результат, "ID", 0));
				ИнформацияКлюча.Вставить("Сертификат", ПолучитьДвоичныеДанныеИзBase64Строки(ДанныеСертификата));
				РезультатЗапроса.Результат = ИнформацияКлюча;
				
				ДопПараметры = Новый Структура("ПроверитьНаличиеВБазе", Истина);
				РезультатОбновления = ПолучитьСертификатыСервиса(НастройкиПользователя, Неопределено, ДопПараметры);
				Если РезультатОбновления.Выполнено Тогда
					НастройкиПользователя.Сертификаты = РезультатОбновления.Результат;
					РезультатЗапроса.МаркерОбновлен = Истина;
					РезультатЗапроса.Вставить("НастройкиПользователя", НастройкиПользователя);
				КонецЕсли;
				
			Иначе	
				РезультатЗапроса.Выполнено = Ложь;
				РезультатЗапроса.Ошибка = СвойствоСтруктуры(РезультатЗапроса.Результат, "ErrorDescription", "");
			КонецЕсли;	
		КонецЕсли;
	КонецЕсли;
		
	СервисКриптографииDSSСлужебный.ПротоколОшибкиПриВызове(РезультатЗапроса, "СоздатьЗакрытыйКлюч", ПараметрыЗапроса, , ПараметрыОперации);
	
	Возврат РезультатЗапроса;
	
КонецФункции

// Устанавливает произвольный параметр для закрытого ключа.
//
// Параметры:
//  ИдентификаторПользователя 	- Структура, СправочникСсылка.УчетныеЗаписиDSS - см. функцию НастройкиПользователяПоУмолчанию()
//  ИдентификаторСертификата	- Число - идентификатор сертификата на сервере DSS
//  ИмяПараметра 				- Строка - имя параметра 
//  ЗначениеПараметра			- Строка - значение параметра
//  ПараметрыОперации 			- Структура, ФиксированнаяСтруктура - позволяет указать дополнительные параметры операции. Проверяемые поля:
//			
// Возвращаемое значение:
//   см. СервисКриптографииDSSКлиентСервер.ОтветСервисаПоУмолчанию
//
Функция УстановитьПараметрЗакрытогоКлюча(ИдентификаторПользователя, 
					ИдентификаторСертификата, 
					ИмяПараметра, 
					ЗначениеПараметра, 
					ПараметрыОперации = Неопределено) Экспорт
	
	НастройкиПользователя	= ПолучитьНастройкиПользователя(ИдентификаторПользователя, ПараметрыОперации);
	РезультатЗапроса		= СервисКриптографииDSSКлиентСервер.ПроверитьВерсиюСервера(НастройкиПользователя, "2");
	
	Если РезультатЗапроса.Выполнено Тогда
		ПараметрыЗапроса		= Новый Структура;
		ПараметрыЗапроса.Вставить("Param", ИмяПараметра);
		ПараметрыЗапроса.Вставить("Data", ЗначениеПараметра);
		
		АдресПодключения	= НастройкиПользователя.Методы.СервисПодписи + "keys/%1/params";
		АдресПодключения	= ЗаполнитьПараметрыСтроки(АдресПодключения, Формат(ИдентификаторСертификата, "ЧГ=0"));
		РезультатЗапроса	= ПодключитьВыполнитьМетодСервиса(НастройкиПользователя, АдресПодключения, ПараметрыЗапроса, "POST", "json", , ПараметрыОперации);
		Если РезультатЗапроса.Выполнено Тогда
			Если СвойствоСтруктуры(РезультатЗапроса.Результат, "IsError", Ложь) Тогда
				РезультатЗапроса.Выполнено = Ложь;
				РезультатЗапроса.Ошибка = СвойствоСтруктуры(РезультатЗапроса.Результат, "ErrorDescription", "");
			КонецЕсли;	
		КонецЕсли;
	КонецЕсли;
		
	СервисКриптографииDSSСлужебный.ПротоколОшибкиПриВызове(РезультатЗапроса, "УстановитьПараметрЗакрытогоКлюча", ПараметрыЗапроса, , ПараметрыОперации);
	
	Возврат РезультатЗапроса;
	
КонецФункции

// Позволяет получить значение параметра закрытого ключа.
//
// Параметры:
//  ИдентификаторПользователя 	- Структура, СправочникСсылка.УчетныеЗаписиDSS - см. функцию НастройкиПользователяПоУмолчанию()
//  ИдентификаторСертификата	- Число - идентификатор сертификата на сервере DSS
//  ИмяПараметра 				- Строка - имя параметра 
//  ПараметрыОперации 			- Структура, ФиксированнаяСтруктура - позволяет указать дополнительные параметры операции. Проверяемые поля:
//			
// Возвращаемое значение:
//   см. СервисКриптографииDSSКлиентСервер.ОтветСервисаПоУмолчанию
//
Функция ПолучитьПараметрЗакрытогоКлюча(ИдентификаторПользователя, 
					ИдентификаторСертификата, 
					ИмяПараметра, 
					ПараметрыОперации = Неопределено) Экспорт
	
	НастройкиПользователя	= ПолучитьНастройкиПользователя(ИдентификаторПользователя, ПараметрыОперации);
	РезультатЗапроса		= СервисКриптографииDSSКлиентСервер.ПроверитьВерсиюСервера(НастройкиПользователя, "2");
	
	Если РезультатЗапроса.Выполнено Тогда
		АдресПодключения 	= НастройкиПользователя.Методы.СервисПодписи + "keys/%1/params?param=%2";
		АдресПодключения	= ЗаполнитьПараметрыСтроки(АдресПодключения, Формат(ИдентификаторСертификата, "ЧГ=0"), ИмяПараметра);
		РезультатЗапроса	= ПодключитьВыполнитьМетодСервиса(НастройкиПользователя, АдресПодключения, Неопределено, "GET", "json", , ПараметрыОперации);
		Если РезультатЗапроса.Выполнено Тогда
			Если НЕ СвойствоСтруктуры(РезультатЗапроса.Результат, "IsError", Ложь) Тогда
				РезультатЗапроса.Выполнено = СвойствоСтруктуры(РезультатЗапроса.Результат, "Value", Истина);
			Иначе	
				РезультатЗапроса.Выполнено = Ложь;
				РезультатЗапроса.Ошибка = СвойствоСтруктуры(РезультатЗапроса.Результат, "ErrorDescription", "");
			КонецЕсли;	
		КонецЕсли;
	КонецЕсли;
		
	СервисКриптографииDSSСлужебный.ПротоколОшибкиПриВызове(РезультатЗапроса, "ПолучитьПараметрЗакрытогоКлюча", ИмяПараметра, , ПараметрыОперации);
	
	Возврат РезультатЗапроса;
	
КонецФункции

#КонецОбласти

#Область АсинхронныеОперации

// Создает операцию подписания в асинхронном режиме.
// Используется API версии 2.0.
//
// Параметры:
//  ИдентификаторПользователя 	- Структура, СправочникСсылка.УчетныеЗаписиDSS - см. функцию НастройкиПользователяПоУмолчанию()
//  ДанныеДокументов			- Массив
//                  			- Строка
//                  			- ДвоичныеДанные
//  СвойствоПодписи				- Структура - изначально заполняется свойствами подписи, подробнее СервисКриптографииDSSКлиентСервер.ПолучитьСвойствоПодписиГост или другими вариантами
//  ИдентификаторСертификата 	- Число - идентификатор сертификата на сервере DSS
//  ПинКод 						- Строка - пин-код для доступа к закрытому ключу сертификата учетной записи
//  ПараметрыОперации 			- Структура, ФиксированнаяСтруктура - позволяет указать дополнительные параметры операции:
//    * АсинхронныйРежим		- Булево - указывает, что подпись нужно сделать в асинхронном режиме, если Истина, то режим подтверждения возможен только через обратный вызов.
//    * ОбратныйВызов 		- Строка - адрес обратного вызова
//    * ПодтверждатьПринудительно - Булево
//    * СовместимостьВерсий	- Булево - по умолчанию Истина, моделируется работа в "старом" режиме
//    * Транзакция			- Булево
//    * ИдентификаторПрофиля 	- Строка
//    * ИдентификаторыСвязанныхДокументов - Строка
//			
// Возвращаемое значение:
//   см. СервисКриптографииDSSКлиентСервер.ОтветСервисаПоУмолчанию
//
Функция ПодписатьАсинхронно(ИдентификаторПользователя, 
					ДанныеДокументов,
					СвойствоПодписи,
					ИдентификаторСертификата,
					ПинКод,
					ПараметрыОперации = Неопределено) Экспорт
	
	
	НастройкиПользователя	= ПолучитьНастройкиПользователя(ИдентификаторПользователя, ПараметрыОперации);
	ВходящиеПараметры		= ПроверитьПараметрыОперации(ПараметрыОперации);
	ИсточникНастроек 		= СервисКриптографииDSSСлужебный.ПолучитьИсточникНастроек(ВходящиеПараметры);
	РезультатЗапроса		= СервисКриптографииDSSКлиентСервер.ПроверитьВерсиюСервера(НастройкиПользователя, "2");
	УстановитьПривилегированныйРежим(Истина);
	ЗначениеПинКода			= ПолучитьЗначениеПароля(ПинКод, НастройкиПользователя, ИсточникНастроек);
	УстановитьПривилегированныйРежим(Ложь);
	
	АсинхронныйРежим		= СвойствоСтруктуры(ПараметрыОперации, "АсинхронныйРежим", Ложь);
	ОбратныйВызов			= СвойствоСтруктуры(ПараметрыОперации, "ОбратныйВызов", "");
	ПодтверждениеОперации	= СвойствоСтруктуры(ПараметрыОперации, "ПодтверждатьПринудительно");
	ПолучитьДокументы		= СвойствоСтруктуры(ПараметрыОперации, "СовместимостьВерсий", Истина);
	ТипРезультата 			= СвойствоСтруктуры(ПараметрыОперации, "ТипРезультата");
	ЭтоТранзакция			= СвойствоСтруктуры(ПараметрыОперации, "Транзакция", Ложь);
	ЭтоПакет				= СвойствоСтруктуры(ПараметрыОперации, "ЭтоПакет", Ложь);
	ИдентификаторПрофиля	= СвойствоСтруктуры(ПараметрыОперации, "ИдентификаторПрофиля");
	ИдентификаторыСвязанныхДокументов = СвойствоСтруктуры(ПараметрыОперации, "ИдентификаторыСвязанныхДокументов");
	
	ЭтоМассив 				= Ложь;
	ТипРезультата 			= СервисКриптографииDSSКлиентСервер.ЗначениеВМассиве(ТипРезультата, ЭтоМассив);
	
	Если РезультатЗапроса.Выполнено Тогда
		ПараметрыЗапроса = Новый Структура;
		
		Если СвойствоПодписи <> Неопределено И НЕ ЭтоТранзакция Тогда
			МассивДокументов = СервисКриптографииDSSКлиентСервер.ЗначениеВМассиве(ДанныеДокументов, ЭтоМассив);
			ДокументыДляОбработки = СервисКриптографииDSSКлиентСервер.ПодготовитьПакетДляПодписи(МассивДокументов);
			
			ТипРезультата = Новый Массив;
			Для Каждого СтрокаМассива Из ДокументыДляОбработки Цикл
				ТипРезультата.Добавить(СтрокаМассива.ВернутьКак);
				Если ЗначениеЗаполнено(СтрокаМассива.RefId) Тогда
					СервисКриптографииDSSКлиентСервер.УдалитьСвойство(СтрокаМассива, , "RefId");
				Иначе
					СервисКриптографииDSSКлиентСервер.УдалитьСвойство(СтрокаМассива, , "Content, ContentInfo");
				КонецЕсли;
			КонецЦикла;
			
			ИмяПараметра = "TSPAddress";
			Если СвойствоПодписи.Свойство(ИмяПараметра) Тогда
				СвойствоПодписи[ИмяПараметра] = ПроверитьПараметрПодписи(НастройкиПользователя, ИмяПараметра, СвойствоПодписи[ИмяПараметра]);
			КонецЕсли;

			ПараметрыЗапроса = СервисКриптографииDSSКлиентСервер.ПолучитьСвойствоПодписиАсинхронной(
							СвойствоПодписи,
							ДокументыДляОбработки,
							ИдентификаторПрофиля,
							ИдентификаторыСвязанныхДокументов);
			
			ПараметрыЗапроса.Вставить("IsAsync", АсинхронныйРежим);
			Если АсинхронныйРежим И ЗначениеЗаполнено(ОбратныйВызов) Тогда
				ПараметрыЗапроса.Вставить("Callback", ОбратныйВызов);
			КонецЕсли;
			Если ПодтверждениеОперации = Истина Тогда
				ПараметрыЗапроса.Вставить("ForceConfirmation", ПодтверждениеОперации);
			КонецЕсли;
			
			ПараметрыЗапроса.Signature.Вставить("CertificateId", ИдентификаторСертификата);
			
			Если ЗначениеЗаполнено(ЗначениеПинКода) Тогда
				ПараметрыЗапроса.Signature.Вставить("PinCode", ЗначениеПинКода);
			КонецЕсли;
			
		Иначе
			Если ЗначениеЗаполнено(ЗначениеПинКода) Тогда
				ПараметрыЗапроса = Новый Структура;
				ПараметрыЗапроса.Вставить("Signature", Новый Структура);
				ПараметрыЗапроса.Signature.Вставить("PinCode", ЗначениеПинКода);
			Иначе
				ПараметрыЗапроса = "{}";
			КонецЕсли;
			
		КонецЕсли;
		
		АдресПодключения	= НастройкиПользователя.Методы.СервисПодписи20 + "signature";
		РезультатЗапроса	= ПодключитьВыполнитьМетодСервиса(НастройкиПользователя, АдресПодключения, ПараметрыЗапроса, "POST", "json", , ПараметрыОперации);
		Если РезультатЗапроса.Выполнено Тогда
			Выжимка = ОписаниеАсинхроннойОперации(РезультатЗапроса.Результат.Operation, "Result.ProcessedDocuments");
			РезультатОперации = Выжимка.ОписаниеОперации;
		
			Если НЕ Выжимка.Выполнено Тогда
				РезультатЗапроса.Выполнено = Ложь;
				РезультатЗапроса.Ошибка = Выжимка.Ошибка;
			ИначеЕсли НЕ РезультатОперации.ТребуетПодтверждения Тогда
				МассивИдентификаторов = Новый Массив;
				МассивСодержимого = Новый Массив;
				Для Каждого СтрокаОтвета Из Выжимка.Действия Цикл
					ИдентификаторДокумента = СвойствоСтруктуры(СтрокаОтвета, "RefId", "");
					СодержимоеДокумента = СвойствоСтруктуры(СтрокаОтвета, "Content", "");
					Если ЗначениеЗаполнено(ИдентификаторДокумента) Тогда
						МассивИдентификаторов.Добавить(ИдентификаторДокумента);
					ИначеЕсли ЗначениеЗаполнено(СодержимоеДокумента) Тогда
						МассивСодержимого.Добавить(СодержимоеДокумента);
					КонецЕсли;
				КонецЦикла;	
				РезультатОперации.Вставить("ИдентификаторыДокументов", МассивИдентификаторов);
				РезультатОперации.Вставить("СодержимоеДокументов", МассивСодержимого);
			Иначе
				ПолучитьДокументы = Ложь;
			КонецЕсли;
			РезультатЗапроса.Результат = РезультатОперации;
			РезультатЗапроса.Вставить("ТипРезультата", ТипРезультата);
		КонецЕсли;
		
	КонецЕсли;
		
	Если ПолучитьДокументы И РезультатЗапроса.Выполнено Тогда
		Если РезультатЗапроса.Результат.ИдентификаторыДокументов.Количество() > 0 Тогда
			РезультатЗапроса = ПолучитьОбработанныеДокументы(НастройкиПользователя, РезультатЗапроса.Результат.ИдентификаторыДокументов, ПараметрыОперации);
		ИначеЕсли РезультатЗапроса.Результат.СодержимоеДокументов.Количество() > 0 Тогда
			РезультатЗапроса.Результат = РезультатЗапроса.Результат.СодержимоеДокументов;
		Иначе
			РезультатЗапроса.Выполнено = Ложь;
		КонецЕсли;
		
		Если РезультатЗапроса.Выполнено Тогда
			КоличествоДокументов = РезультатЗапроса.Результат.Количество();
			Если ТипРезультата.Количество() <> КоличествоДокументов Тогда
				ТипРезультата = Новый Массив(КоличествоДокументов);
			КонецЕсли;
			
			ПодписанныеДокументы = Новый Массив;
			
			Для Счетчик = 0 По КоличествоДокументов - 1 Цикл
				ТекущийЭлемент 	= ТипРезультата[Счетчик];
				Подписанный		= СервисКриптографииDSSСлужебный.ПодготовитьРезультатЗапроса(РезультатЗапроса.Результат[Счетчик], ТекущийЭлемент);
				ПодписанныеДокументы.Добавить(Подписанный);
			КонецЦикла;

			Если ЭтоМассив ИЛИ ЭтоПакет Тогда
				РезультатЗапроса.Вставить("Результат", ПодписанныеДокументы);
			Иначе
				РезультатЗапроса.Вставить("Результат", ПодписанныеДокументы[0]);
			КонецЕсли;
			
		КонецЕсли;
		
	КонецЕсли;
		
	СервисКриптографииDSSСлужебный.ПротоколОшибкиПриВызове(РезультатЗапроса, "ПодписатьАсинхронно", СвойствоПодписи, , ПараметрыОперации);
	
	ЗначениеПинКода = Неопределено;
	ПараметрыЗапроса = Неопределено;
	
	Возврат РезультатЗапроса;
	
КонецФункции

// Расшифровывает данные с использованием переданного идентификатора сертификата пользователя.
// Используется API версии 2.0.
//
// Параметры:
//  ИдентификаторПользователя 	- СправочникСсылка.УчетныеЗаписиDSS 
//                            	- Структура - см. НастройкиПользователяПоУмолчанию()
//  ДанныеДокумента 			- ДвоичныеДанные, Строка - один файл, который необходимо обработать,
//								см. функцию СервисКриптографииDSSКлиентСервер.ПодготовитьДанныеДокумента().
//  ИдентификаторСертификата 	- Число - идентификатор сертификата на сервере DSS
//  ТипШифрования 				- Строка - тип шифрования, допустимые варианты: CMS или XML
//  ПинКод 						- Строка - пин-код для доступа к закрытому ключу сертификата учетной записи
//  ПараметрыОперации 			- Структура, ФиксированнаяСтруктура - позволяет указать дополнительные параметры операции. Проверяемы поля:
//    * Транзакция 			- Булево - признак осуществления операции в рамках подтверждения
//    * ТипРезультата 		- Строка - в каком формате возвращать результат, если использовалась транзакция
//			
// Возвращаемое значение:
//   см. СервисКриптографииDSSКлиентСервер.ОтветСервисаПоУмолчанию
//
Функция РасшифроватьАсинхронно(
			ИдентификаторПользователя, 
			ДанныеДокумента, 
			ИдентификаторСертификата, 
			ТипШифрования = "CMS", 
			ПинКод = "", 
			ПараметрыОперации = Неопределено) Экспорт
	
	НастройкиПользователя	= ПолучитьНастройкиПользователя(ИдентификаторПользователя, ПараметрыОперации);
	ВходящиеПараметры		= ПроверитьПараметрыОперации(ПараметрыОперации);
	ИсточникНастроек 		= СервисКриптографииDSSСлужебный.ПолучитьИсточникНастроек(ВходящиеПараметры);
	РезультатЗапроса		= СервисКриптографииDSSКлиентСервер.ПроверитьВерсиюСервера(НастройкиПользователя, "2");
	УстановитьПривилегированныйРежим(Истина);
	ЗначениеПинКода			= ПолучитьЗначениеПароля(ПинКод, НастройкиПользователя, ИсточникНастроек);
	УстановитьПривилегированныйРежим(Ложь);
	
	АсинхронныйРежим		= СвойствоСтруктуры(ПараметрыОперации, "АсинхронныйРежим", Ложь);
	ОбратныйВызов			= СвойствоСтруктуры(ПараметрыОперации, "ОбратныйВызов", "");
	ПодтверждениеОперации	= СвойствоСтруктуры(ПараметрыОперации, "ПодтверждатьПринудительно");
	СовместимостьВерсий		= СвойствоСтруктуры(ПараметрыОперации, "СовместимостьВерсий", Истина);
	ЭтоТранзакция			= СвойствоСтруктуры(ПараметрыОперации, "Транзакция", Ложь);
	ЭтоПакет				= СвойствоСтруктуры(ПараметрыОперации, "ЭтоПакет", Ложь);
	ТипРезультата 			= СвойствоСтруктуры(ПараметрыОперации, "ТипРезультата");
	
	ЭтоМассив 				= Ложь;
	ТипРезультата 			= СервисКриптографииDSSКлиентСервер.ЗначениеВМассиве(ТипРезультата, ЭтоМассив);
	
	Если РезультатЗапроса.Выполнено Тогда
		ПараметрыЗапроса = Новый Структура;
		
		Если ДанныеДокумента <> Неопределено И НЕ ЭтоТранзакция Тогда
			МассивДокументов = СервисКриптографииDSSКлиентСервер.ЗначениеВМассиве(ДанныеДокумента, ЭтоМассив);
			ДокументыДляОбработки = СервисКриптографииDSSКлиентСервер.ПодготовитьПакетДляПодписи(МассивДокументов);
			
			ТипРезультата = Новый Массив;
			Для Каждого СтрокаМассива Из ДокументыДляОбработки Цикл
				ТипРезультата.Добавить(СтрокаМассива.ВернутьКак);
				Если ЗначениеЗаполнено(СтрокаМассива.RefId) Тогда
					СервисКриптографииDSSКлиентСервер.УдалитьСвойство(СтрокаМассива, , "RefId");
				Иначе
					СервисКриптографииDSSКлиентСервер.УдалитьСвойство(СтрокаМассива, , "Content, ContentInfo");
				КонецЕсли;
			КонецЦикла;
			
			ПараметрыЗапроса.Вставить("IsAsync", АсинхронныйРежим);
			ПараметрыЗапроса.Вставить("Callback", ОбратныйВызов);
			Если ПодтверждениеОперации = Истина Тогда
				ПараметрыЗапроса.Вставить("ForceConfirmation", ПодтверждениеОперации);
			КонецЕсли;
			
			ПараметрыЗапроса.Вставить("BinaryData", ДокументыДляОбработки);
			ПараметрыЗапроса.Вставить("Decryption", Новый Структура);
			ПараметрыЗапроса.Decryption.Вставить("Type", ?(ТипШифрования = "XML", 1, 0));
			
			Если ЗначениеЗаполнено(ИдентификаторСертификата) Тогда
				ПараметрыЗапроса.Decryption.Вставить("CertificateId", ИдентификаторСертификата);
			КонецЕсли;
			
			Если ЗначениеЗаполнено(ЗначениеПинКода) Тогда
				ПараметрыЗапроса.Decryption.Вставить("PinCode", ЗначениеПинКода);
			КонецЕсли;
			
			Если ПараметрыОперации = Неопределено Тогда
				ПараметрыЗапроса.Decryption.Вставить("Parameters", Новый Структура);
			ИначеЕсли ПараметрыОперации.Свойство("ПараметрыШифрования") Тогда
				ПараметрыЗапроса.Decryption.Вставить("Parameters", ПараметрыОперации.ПараметрыШифрования);
			КонецЕсли;	
			
		Иначе
			ПараметрыЗапроса = Новый Структура;
			Если ЗначениеЗаполнено(ЗначениеПинКода) Тогда
				ПараметрыЗапроса.Вставить("Decryption", Новый Структура);
				ПараметрыЗапроса.Decryption.Вставить("PinCode", ЗначениеПинКода);
			Иначе
				ПараметрыЗапроса = "{}";
			КонецЕсли;
			
		КонецЕсли;
		
		АдресПодключения	= НастройкиПользователя.Методы.СервисПодписи20 + "decryption";
		РезультатЗапроса	= ПодключитьВыполнитьМетодСервиса(НастройкиПользователя, АдресПодключения, ПараметрыЗапроса, "POST", "json", , ПараметрыОперации);
		Если РезультатЗапроса.Выполнено Тогда
			Выжимка = ОписаниеАсинхроннойОперации(РезультатЗапроса.Результат.Operation, "Result.ProcessedDocuments");
			РезультатОперации = Выжимка.ОписаниеОперации;
			Если НЕ Выжимка.Выполнено Тогда
				РезультатЗапроса.Выполнено = Ложь;
				РезультатЗапроса.Ошибка = Выжимка.Ошибка;
			ИначеЕсли НЕ РезультатОперации.ТребуетПодтверждения Тогда
				МассивДокументов = Новый Массив;
				Для Каждого СтрокаОтвета Из Выжимка.Действия Цикл
					МассивДокументов.Добавить(СвойствоСтруктуры(СтрокаОтвета, "RefId", ""));
				КонецЦикла;	
				РезультатОперации.Вставить("ИдентификаторыДокументов", МассивДокументов);
			Иначе
				СовместимостьВерсий = Ложь;
			КонецЕсли;
			РезультатЗапроса.Результат = РезультатОперации;
			РезультатЗапроса.Вставить("ТипРезультата", ТипРезультата);
		КонецЕсли;
	КонецЕсли;
	
	Если РезультатЗапроса.Выполнено И СовместимостьВерсий Тогда
		РезультатЗапроса = ПолучитьОбработанныеДокументы(НастройкиПользователя, РезультатЗапроса.Результат.ИдентификаторыДокументов, ПараметрыОперации);
		
		Если РезультатЗапроса.Выполнено Тогда
			КоличествоДокументов = РезультатЗапроса.Результат.Количество();
			Если ТипРезультата.Количество() <> КоличествоДокументов Тогда
				ТипРезультата = Новый Массив(КоличествоДокументов);
			КонецЕсли;
			
			РасшифрованныеДокументы = Новый Массив;
			
			Для Счетчик = 0 По КоличествоДокументов - 1 Цикл
				ТекущийЭлемент 	= ТипРезультата[Счетчик];
				Подписанный		= СервисКриптографииDSSСлужебный.ПодготовитьРезультатЗапроса(РезультатЗапроса.Результат[Счетчик], ТекущийЭлемент);
				РасшифрованныеДокументы.Добавить(Подписанный);
			КонецЦикла;

			Если ЭтоМассив ИЛИ ЭтоПакет Тогда
				РезультатЗапроса.Вставить("Результат", РасшифрованныеДокументы);
			Иначе
				РезультатЗапроса.Вставить("Результат", РасшифрованныеДокументы[0]);
			КонецЕсли;
			
		КонецЕсли;
		
	КонецЕсли;
	
	СервисКриптографииDSSСлужебный.ПротоколОшибкиПриВызове(РезультатЗапроса, "РасшифроватьАсинхронно", ИдентификаторСертификата, , ПараметрыОперации);
	
	ЗначениеПинКода = Неопределено;
	ПараметрыЗапроса = Неопределено;
	
	Возврат РезультатЗапроса;
	
КонецФункции

// Получает список идентификаторов сертификатов с помощью которых были зашифрованы данные, для указанной учетной записи сервиса.
// Используется API версии 2.0.
// Если документ не содержит подходящих сертификатов, то массив пустой.
//
// Параметры:
//   ИдентификаторПользователя 	- СправочникСсылка.УчетныеЗаписиDSS 
//                             	- Структура - см. НастройкиПользователяПоУмолчанию()
//   ДанныеДокумента 			- Массив из Строка, Строка - идентификатор файла или файлов, которые необходимо обработать,
//   ТипШифрования 				- Строка - тип шифрования, варианты: CMS или XML
//   ПараметрыОперации 			- Структура, ФиксированнаяСтруктура - позволяет указать дополнительные параметры операции.
//			
// Возвращаемое значение:
//   см. СервисКриптографииDSSКлиентСервер.ОтветСервисаПоУмолчанию
//	
Функция СертификатыРасшифрованияАсинхронно(ИдентификаторПользователя, ДанныеДокумента, ТипШифрования = "CMS", ПараметрыОперации = Неопределено) Экспорт
	
	НастройкиПользователя	= ПолучитьНастройкиПользователя(ИдентификаторПользователя, ПараметрыОперации);
	РезультатЗапроса		= СервисКриптографииDSSКлиентСервер.ПроверитьВерсиюСервера(НастройкиПользователя, "2");
	СовместимостьВерсий		= СвойствоСтруктуры(ПараметрыОперации, "СовместимостьВерсий", Истина);
	
	Если РезультатЗапроса.Выполнено Тогда
		ПараметрыЗапроса 	= Новый Структура;
		
		ЭтоМассив = Ложь;
		МассивДокументов = СервисКриптографииDSSКлиентСервер.ЗначениеВМассиве(ДанныеДокумента, ЭтоМассив);
		ДокументыДляОбработки = СервисКриптографииDSSКлиентСервер.ПодготовитьПакетДляПодписи(МассивДокументов);
		
		Для Каждого СтрокаМассива Из ДокументыДляОбработки Цикл
			Если ЗначениеЗаполнено(СтрокаМассива.RefId) Тогда
				СервисКриптографииDSSКлиентСервер.УдалитьСвойство(СтрокаМассива, , "RefId");
			Иначе
				СервисКриптографииDSSКлиентСервер.УдалитьСвойство(СтрокаМассива, , "Content, ContentInfo");
			КонецЕсли;
		КонецЦикла;
		
		ПараметрыЗапроса = Новый Структура();
		ПараметрыЗапроса.Вставить("BinaryData", ДокументыДляОбработки);
		ПараметрыЗапроса.Вставить("Type", ТипШифрования);
			
		АдресПодключения	= НастройкиПользователя.Методы.СервисПодписи20 + "parse";
		РезультатЗапроса	= ПодключитьВыполнитьМетодСервиса(НастройкиПользователя, АдресПодключения, ПараметрыЗапроса, "POST", "json", , ПараметрыОперации);
		Если РезультатЗапроса.Выполнено Тогда
			МассивДокументов = Новый Массив;
			Выжимка = ОписаниеАсинхроннойОперации(РезультатЗапроса.Результат.Operation, "Result.ParsedDocuments");
			РезультатОперации = Выжимка.ОписаниеОперации;
			Если НЕ Выжимка.Выполнено Тогда
				РезультатЗапроса.Выполнено = Ложь;
				РезультатЗапроса.Ошибка = Выжимка.Ошибка;
			ИначеЕсли НЕ РезультатОперации.ТребуетПодтверждения Тогда
				Для Каждого СтрокаМассива Из Выжимка.Действия Цикл
					НоваяСтрока = Новый Структура;
					НоваяСтрока.Вставить("ИдентификаторДокумента", СтрокаМассива.OriginalRefId);
					НоваяСтрока.Вставить("Сертификаты", СтрокаМассива.CertificateIds);
					МассивДокументов.Добавить(НоваяСтрока);
				КонецЦикла;	
			КонецЕсли;
			
			РезультатЗапроса.Результат = МассивДокументов;
			
		КонецЕсли;
	КонецЕсли;
	
	Если РезультатЗапроса.Выполнено И СовместимостьВерсий Тогда
		МассивСертификатов = Новый Массив;
		Для Каждого СтрокаМассива Из РезультатЗапроса.Результат Цикл
			МассивСертификатов.Добавить(СтрокаМассива.Сертификаты);
		КонецЦикла;
		РезультатЗапроса.Результат = МассивСертификатов;
	КонецЕсли;
	
	Если НЕ РезультатЗапроса.Выполнено Тогда
		РезультатЗапроса.Результат = Новый Массив;
	ИначеЕсли ЭтоМассив Тогда
		РезультатЗапроса.Результат = МассивДокументов;
	ИначеЕсли РезультатЗапроса.Результат.Количество() > 0 Тогда
		РезультатЗапроса.Результат = РезультатЗапроса.Результат[0];
	КонецЕсли;
	
	СервисКриптографииDSSСлужебный.ПротоколОшибкиПриВызове(РезультатЗапроса, "СертификатыРасшифрованияАсинхронно", ДанныеДокумента, , ПараметрыОперации);
	
	ПараметрыЗапроса = Неопределено;
	
	Возврат РезультатЗапроса;
	
КонецФункции

// Шифрует данные для переданного списка сертификатов получателей.
// Используется API версии 2.0.
//
// Параметры:
//  ИдентификаторПользователя 	- СправочникСсылка.УчетныеЗаписиDSS 
//                            	- Структура - см. НастройкиПользователяПоУмолчанию()
//  ДанныеДокумента 			- Массив из Строка, Строка - идентификатор файла или файлов, которые необходимо обработать,
//  СертификатыПолучателей 		- ДвоичныеДанные, Структура, ФиксированнаяСтруктура, Массив, ФиксированныйМассив - 
//								сертификаты получателей зашифрованного сообщения, см. функцию ПолучитьДвоичныеДанныеСертификатов() 
//  ТипШифрования 				- Строка - тип шифрования, варианты: CMS или XML
//  ПараметрыОперации 			- Структура, ФиксированнаяСтруктура - позволяет указать дополнительные параметры операции. Проверяемые поля:
//    * ПараметрыШифрования		- Структура - содержит дополнительные поля для шифрования, см. документацию по сервису 
//			
// Возвращаемое значение:
//   см. СервисКриптографииDSSКлиентСервер.ОтветСервисаПоУмолчанию
//
Функция ЗашифроватьАсинхронно(ИдентификаторПользователя, 
					ДанныеДокумента, 
					СертификатыПолучателей, 
					ТипШифрования = "CMS", 
					ПараметрыОперации = Неопределено) Экспорт
	
	НастройкиПользователя	= ПолучитьНастройкиПользователя(ИдентификаторПользователя, ПараметрыОперации);
	СписокСертификатов		= ПолучитьДвоичныеДанныеСертификатов(СертификатыПолучателей);
	РезультатЗапроса		= СервисКриптографииDSSКлиентСервер.ПроверитьВерсиюСервера(НастройкиПользователя, "2");
	СовместимостьВерсий		= СвойствоСтруктуры(ПараметрыОперации, "СовместимостьВерсий", Истина);
	ЭтоМассив 				= Ложь;
	
	Если РезультатЗапроса.Выполнено Тогда
		ПараметрыЗапроса = Новый Структура;
		
		ТипРезультата = Новый Массив;
		МассивФайлов = СервисКриптографииDSSКлиентСервер.ЗначениеВМассиве(ДанныеДокумента, ЭтоМассив);
		МассивФайлов = СервисКриптографииDSSКлиентСервер.ПодготовитьПакетДляПодписи(МассивФайлов);
		
		Для Каждого СтрокаМассива Из МассивФайлов Цикл
			ТипРезультата.Добавить(СтрокаМассива.ВернутьКак);
			Если ЗначениеЗаполнено(СтрокаМассива.RefId) Тогда
				СервисКриптографииDSSКлиентСервер.УдалитьСвойство(СтрокаМассива, , "RefId");
			Иначе
				СервисКриптографииDSSКлиентСервер.УдалитьСвойство(СтрокаМассива, , "Content, ContentInfo");
			КонецЕсли;
		КонецЦикла;
		
		ПараметрыЗапроса = Новый Структура;
		ПараметрыЗапроса.Вставить("BinaryData", МассивФайлов);
		ПараметрыЗапроса.Вставить("Encryption", Новый Структура);
		ПараметрыЗапроса.Encryption.Вставить("Type", ?(ТипШифрования = "XML", 1, 0));
		ПараметрыЗапроса.Encryption.Вставить("Certificates", СписокСертификатов);
		Если ПараметрыОперации = Неопределено Тогда
			ПараметрыЗапроса.Encryption.Вставить("Parameters", Новый Структура);
		ИначеЕсли ПараметрыОперации.Свойство("ПараметрыШифрования") Тогда
			ПараметрыЗапроса.Encryption.Вставить("Parameters", ПараметрыОперации.ПараметрыШифрования);
		КонецЕсли;	
		
		Если СписокСертификатов.Количество() > 0 Тогда
			АдресПодключения	= НастройкиПользователя.Методы.СервисПодписи20 + "encryption";
			РезультатЗапроса	= ПодключитьВыполнитьМетодСервиса(НастройкиПользователя, АдресПодключения, ПараметрыЗапроса, "POST", "json", , ПараметрыОперации);
			Если РезультатЗапроса.Выполнено Тогда
				Выжимка = ОписаниеАсинхроннойОперации(РезультатЗапроса.Результат.Operation, "Result.ProcessedDocuments");
				РезультатОперации = Выжимка.ОписаниеОперации;
				
				МассивДокументов = Новый Массив;
				Если НЕ Выжимка.Выполнено Тогда
					РезультатЗапроса.Выполнено = Ложь;
					РезультатЗапроса.Ошибка = Выжимка.Ошибка;
				ИначеЕсли НЕ РезультатОперации.ТребуетПодтверждения Тогда
					Для Каждого СтрокаМассива Из Выжимка.Действия Цикл
						НоваяСтрока = Новый Структура;
						НоваяСтрока.Вставить("ИдентификаторДокумента", СтрокаМассива.OriginalRefId);
						НоваяСтрока.Вставить("ЗашифрованныйДокумент", СтрокаМассива.RefId);
						МассивДокументов.Добавить(НоваяСтрока);	
					КонецЦикла;
					РезультатЗапроса.Результат = МассивДокументов;
				КонецЕсли;
				
			КонецЕсли;
		Иначе
			РезультатЗапроса = СервисКриптографииDSSКлиентСервер.ОтветСервисаПоУмолчанию(Ложь);
			СервисКриптографииDSSСлужебный.ПолучитьОписаниеОшибки(РезультатЗапроса, "ПараметрыЗашифрования");
		КонецЕсли;
		
	КонецЕсли;
	
	Если РезультатЗапроса.Выполнено И СовместимостьВерсий Тогда
		Идентификаторы = Новый Массив;
		Для Каждого СтрокаМассива Из РезультатЗапроса.Результат Цикл
			Идентификаторы.Добавить(СтрокаМассива.ЗашифрованныйДокумент);
		КонецЦикла;
		РезультатЗапроса = ПолучитьОбработанныеДокументы(НастройкиПользователя, Идентификаторы, ПараметрыОперации);
		
		МассивДокументов = Новый Массив;
		Если РезультатЗапроса.Выполнено Тогда
			Для Счетчик = 0 По РезультатЗапроса.Результат.Количество() - 1 Цикл
				МассивДокументов.Добавить(СервисКриптографииDSSСлужебный.ПодготовитьРезультатЗапроса(
											РезультатЗапроса.Результат[Счетчик], ТипРезультата[Счетчик]));
			КонецЦикла;
		КонецЕсли;
		
		РезультатЗапроса.Результат = МассивДокументов							
	КонецЕсли;
	
	Если РезультатЗапроса.Выполнено И НЕ ЭтоМассив Тогда
		Если РезультатЗапроса.Результат.Количество() > 0 Тогда
			РезультатЗапроса.Результат = РезультатЗапроса.Результат[0]; 
		КонецЕсли;
	КонецЕсли;
	
	СервисКриптографииDSSСлужебный.ПротоколОшибкиПриВызове(РезультатЗапроса, "ЗашифроватьСинхронно", ПараметрыЗапроса, , ПараметрыОперации);
	
	Возврат РезультатЗапроса;
	
КонецФункции

// Получает сведения об операции начатой на сервере облачной подписи.
//
// Параметры:
//  ИдентификаторПользователя 	- Структура, СправочникСсылка.УчетныеЗаписиDSS - см. функцию НастройкиПользователяПоУмолчанию()
//  ИдентификаторОперации 		- Строка - идентификатор операции ранее созданной на сервере
//  ПараметрыОперации 			- Структура, ФиксированнаяСтруктура - позволяет указать дополнительные параметры операции. Проверяемы поля:
//			
// Возвращаемое значение:
//   см. СервисКриптографииDSSКлиентСервер.ОтветСервисаПоУмолчанию
//
Функция СведенияОбОперации(ИдентификаторПользователя, 
					ИдентификаторОперации,
					ПараметрыОперации = Неопределено) Экспорт
	
	НастройкиПользователя	= ПолучитьНастройкиПользователя(ИдентификаторПользователя, ПараметрыОперации);
	РезультатЗапроса		= СервисКриптографииDSSКлиентСервер.ПроверитьВерсиюСервера(НастройкиПользователя, "2");
	
	Если РезультатЗапроса.Выполнено Тогда
		АдресПодключения	= ЗаполнитьПараметрыСтроки(НастройкиПользователя.Методы.СервисОпераций + "/%1", ИдентификаторОперации);
		РезультатЗапроса	= ПодключитьВыполнитьМетодСервиса(НастройкиПользователя, АдресПодключения, Неопределено, "GET", "json", , ПараметрыОперации);
		Если РезультатЗапроса.Выполнено Тогда
			Выжимка = ОписаниеАсинхроннойОперации(РезультатЗапроса.Результат, "Actions");
			РезультатОперации = Выжимка.ОписаниеОперации;
			Если НЕ Выжимка.Выполнено Тогда
				РезультатЗапроса.Выполнено = Ложь;
				РезультатЗапроса.Ошибка = Выжимка.Ошибка;
			ИначеЕсли НЕ РезультатОперации.ТребуетПодтверждения Тогда
				МассивДокументов = Новый Массив;
				Для Каждого СтрокаОтвета Из Выжимка.Действия Цикл
					МассивДокументов.Добавить(СвойствоСтруктуры(СтрокаОтвета, "ResultValue", ""));
				КонецЦикла;	
				РезультатОперации.Вставить("ИдентификаторыДокументов", МассивДокументов);
			КонецЕсли;
			РезультатЗапроса.Результат = РезультатОперации;
		КонецЕсли;
	КонецЕсли;
		
	СервисКриптографииDSSСлужебный.ПротоколОшибкиПриВызове(РезультатЗапроса, "СведенияОбОперации", ИдентификаторОперации, , ПараметрыОперации);
	
	Возврат РезультатЗапроса;
	
КонецФункции

#КонецОбласти

#Область Прочие

// Возвращает статус использования облачной подписи в рамках базы
//
// Возвращаемое значение:
//  Булево
//
Функция ИспользоватьСервисОблачнойПодписи() Экспорт
	
	Результат = ПолучитьФункциональнуюОпцию("ИспользоватьСервисDSS");
	
	Возврат Результат;
	
КонецФункции

// Возвращает возможность использования дополнительных возможностей для работы с облачной подписью, такими как
// формирование заявления для выпуска сертификата, заявление на изменение параметров подключения.
//
// Возвращаемое значение:
//  Булево
//
Функция ИспользоватьРасширенныеВозможности() Экспорт
	
	Результат = ОбщегоНазначения.РазделениеВключено()
				И ИспользоватьСервисОблачнойПодписи();
				
	Результат = Ложь;
	
	Возврат Результат;
	
КонецФункции


// Меняет статус использования облачной подписи в рамках базы
//
// Параметры:
//  НовыйСтатус - Булево
//
Процедура ИзменитьИспользованиеСервисаОблачнойПодписи(НовыйСтатус) Экспорт
	
	Если ИспользоватьСервисОблачнойПодписи() <> НовыйСтатус Тогда
		Константы.ИспользоватьСервисDSS.Установить(НовыйСтатус);
	КонецЕсли;	
	
КонецПроцедуры

// Перечисляет список допустимых способов первичной аутентификации (авторизации) 
//
// Параметры:
//  СервисПодписи - СправочникСсылка.ЭкземплярыСервераDSS - получает полный список авторизации с учетом ограничений
//
// Возвращаемое значение:
//  Массив - содержит значения из ПеречислениеСсылка.СпособыАвторизацииDSS
//
Функция СписокПервичнойАвторизации(СервисПодписи) Экспорт
	
	Результат = Новый Массив;
	
	ПолныйСписок = СервисКриптографииDSSСлужебный.ДоступныеСпособыПервичнойАвторизации();
	СписокОграничений = СервисКриптографииDSSСлужебный.СпособыАвторизацииСОграничениями(СервисПодписи);
	
	Для Каждого СтрокаМассива Из ПолныйСписок Цикл
		Если СписокОграничений.Найти(СтрокаМассива) <> Неопределено Тогда
			Результат.Добавить(СтрокаМассива);
		КонецЕсли;	
	КонецЦикла;
	
	Если Результат.Количество() = 0 Тогда
		Результат = ПолныйСписок;
	КонецЕсли;
	
	СервисКриптографииDSSПереопределяемый.СписокПервичнойАвторизации(Результат);
	
	Возврат Результат;
	
КонецФункции

// Перечисляет список допустимых способов вторичной авторизации (подтверждения операций) 
//
// Параметры:
//  СервисПодписи - СправочникСсылка.ЭкземплярыСервераDSS - получает полный список авторизации с учетом ограничений
//
// Возвращаемое значение:
//  Массив - содержит значения из ПеречислениеСсылка.СпособыАвторизацииDSS
//
Функция СписокВторичнойАвторизации(СервисПодписи) Экспорт
	
	Результат = Новый Массив;
	
	ПолныйСписок = СервисКриптографииDSSСлужебный.ДоступныеСпособыВторичнойАвторизации();
	СписокОграничений = СервисКриптографииDSSСлужебный.СпособыАвторизацииСОграничениями(СервисПодписи);
	
	Для Каждого СтрокаМассива Из ПолныйСписок Цикл
		Если СписокОграничений.Найти(СтрокаМассива) <> Неопределено Тогда
			Результат.Добавить(СтрокаМассива);
		КонецЕсли;	
	КонецЦикла;
	
	Если Результат.Количество() = 0 Тогда
		Результат = ПолныйСписок;
	КонецЕсли;
	
	СервисКриптографииDSSПереопределяемый.СписокВторичнойАвторизации(Результат);
	
	Возврат Результат;
	
КонецФункции

// Формирует структуру с информацией о доступных указанной учетной записи УЦ, Криптопровайдерах.
// Шаблонах и Полях запроса на основе данных политики авторизованного пользователя сервиса. 
// Данная информация необходима при формировании запроса на сертификат отправляемый на сервер.
// 
// Параметры:
//  ИдентификаторПользователя	- СправочникСсылка.УчетныеЗаписиDSS, 
//                           	- Структура
//  ПараметрыОперации			- Структура, ФиксированнаяСтруктура - позволяет указать дополнительные параметры операции.
// 
// Возвращаемое значение:
//  Структура:
//    * Заполнено 			- Булево - если данные актуальны для данной учетной, т.е. была аутентификация
//      * Криптопровайдеры 		- Массив из Структура:
//      ** Идентификатор 	- Строка - идентификатор криптопровайдера зарегистрированный на сервисе
//      ** Описание 		- Строка - пользовательское представление 
//    * УдостоверяющиеЦентры - Массив из Структура:
//      ** Имя 				- Строка - представление УЦ
//      ** Идентификатор 	- Строка - идентификатор который передается в сервис криптографии DSS
//      ** Сторонний		- Булево - если сторонний, то потребует отдельной операции установки сертификата
//      ** Шаблоны 			- см. ПолучитьРеестрШаблоновУдостоверяющегоЦентра
//      ** ИменаПолей 		- см. ПолучитьРеестрПолейУдостоверяющегоЦентра
//
Функция ПолучитьИнформациюУдостоверяющихЦентров(ИдентификаторПользователя, ПараметрыОперации = Неопределено) Экспорт
	
	НастройкиПользователя	= ПолучитьНастройкиПользователя(ИдентификаторПользователя, ПараметрыОперации);
	
	Результат = Новый Структура();
	
	Результат.Вставить("УдостоверяющиеЦентры", СервисКриптографииDSSСлужебный.СкопироватьСтруктуру(НастройкиПользователя.Политика.УЦ));
	Результат.Вставить("КриптоПровайдеры", СервисКриптографииDSSСлужебный.СкопироватьСтруктуру(НастройкиПользователя.Политика.Криптопровайдеры));
	Результат.Вставить("Заполнено", НастройкиПользователя.Политика.Заполнено);
	
	Возврат Результат;
	
КонецФункции

// Формирует массив полей запроса на сертификат, которые допустимы для указанного УЦ. 
// При запросе к сервису нельзя указывать "лишние" поля, также есть поля, заполнение и передача которых является
// обязательными.
//
// Параметры:
//  УдостоверяющийЦентр 		- Структура - содержит информацию об удостоверяющем центре см. функцию ПолучитьИнформациюУдостоверяющегоЦентра()
//
// Возвращаемое значение:
//  Массив из Структура:
//    * OID 					- Строка - значение кода поля
//    * Имя 					- Строка - имя поля
//    * Длина 				- Число - содержит информацию об ограничении длины поля
//    * Представление 		- Строка - пользовательское представление
//    * Обязательно 			- Булево - если Истина, поля должны заполнено и передано, иначе сервер формирует ошибку
//
Функция ПолучитьРеестрПолейУдостоверяющегоЦентра(УдостоверяющийЦентр) Экспорт
	
	Результат	= Новый Массив;
	ВсеПоля		= СервисКриптографииDSSASNКлиентСервер.ОпределитьТип_OID(Неопределено, "10");
	
	Для каждого СтрокаМассива Из УдостоверяющийЦентр.ИменаПолей Цикл
		НашлиЭлемент = ВсеПоля[СтрокаМассива["OID"]];
		
		Если НашлиЭлемент <> Неопределено Тогда
			НашлиЭлемент.Обязательно = СтрокаМассива["IsRequired"];
			Результат.Добавить(НашлиЭлемент);
		КонецЕсли;
		
	КонецЦикла;	
	
	Возврат Результат;
	
КонецФункции	

// Формирует массив шаблонов допустимые в этом УЦ
// 
// Параметры:
//  УдостоверяющийЦентр	- Структура:
//    * Шаблоны			- Массив из Структура:
//      ** Шаблон		- Строка
//      ** Наименование	- Строка
//
// Возвращаемое значение:
//  Массив из Структура:
//    * Шаблон 				- Строка - значение шаблона,
//    * Наименование 		- Строка - пользовательское представление
//
Функция ПолучитьРеестрШаблоновУдостоверяющегоЦентра(УдостоверяющийЦентр) Экспорт
	
	Результат	= Новый Массив;
	
	Для каждого СтрокаМассива Из УдостоверяющийЦентр.Шаблоны Цикл
		НоваяСтрока = Новый Структура();
		НоваяСтрока.Вставить("Шаблон", СтрокаМассива.Шаблон);
		НоваяСтрока.Вставить("Наименование", СтрокаМассива.Наименование);
		Результат.Добавить(НоваяСтрока);
	КонецЦикла;	
	
	Возврат Результат;
	
КонецФункции

// Служит для установки текущего пользователя для последующей работы с сервисом.
// Предусмотрена для случая, когда нужно указать конкретного пользователя, при использовании стандартного АПИ БСП, 
// в котором данный параметры не предусмотрен.
//
// Параметры:
//  СсылкаУчетнойЗаписи - СправочникСсылка.УчетныеЗаписиDSS - идентифицирующий признак в сеансовых данных
//  ИсточникНастроек 	- Неопределено, Строка - варианты определенные в функциях
//						СервисКриптографииDSSКлиентСервер.ИсточникНастроекПараметрыСеанса(),
//						СервисКриптографииDSSКлиентСервер.ИсточникНастроекХранилище().
//	
Процедура УстановитьТекущегоПользователя(СсылкаУчетнойЗаписи, ИсточникНастроек = Неопределено) Экспорт
	
	ТекущиеНастройки 	= СервисКриптографииDSSСлужебный.ПолучитьКонтейнерНастроек(ИсточникНастроек);
	ТекущиеНастройки.ТекущийПользователь = СсылкаУчетнойЗаписи;
	СервисКриптографииDSSСлужебный.УстановитьКонтейнерНастроек(ТекущиеНастройки, ИсточникНастроек);
	
КонецПроцедуры

// Служит для создания новой учетной записи сервиса облачной подписи или обновления существующего элемента
//
// Параметры:
//  НастройкиУчетнойЗаписи - Структура:
//    * Владелец - СправочникСсылка.ЭкземплярыСервераDSS
//    * Логин - Строка
//    * ПервичнаяАутентификация - ПеречислениеСсылка.СпособыАвторизацииDSS
//    * ВторичнаяАвторизация - ПеречислениеСсылка.СпособыАвторизацииDSS - необязательный
//    * Комментарий - Строка - необязательный
//
// Возвращаемое значение:
//  СправочникСсылка.УчетныеЗаписиDSS
//
Функция ОбновитьДанныеУчетнойЗаписиОблачнойПодписи(НастройкиУчетнойЗаписи) Экспорт
	
	Возврат СервисКриптографииDSSСлужебный.СоздатьУчетнуюЗаписьОблачнойПодписи(НастройкиУчетнойЗаписи);
	
КонецФункции

// Служит для создания нового подключения сервиса облачной подписи или обновления существующего элемента.
// Если был найден дублирующий элемент по полям: АдресСервера и ИдентификаторЦИ, то будет произведено обновление элемента.
//
// Параметры:
//  НастройкиСервиса - Структура:
//    * АдресСервера 				- Строка - поле поиска дублера
//    * СервисПроверки 			- Строка
//    * СервисПодписи 			- Строка
//    * СервисИдентификации 		- Строка
//    * ИдентификаторЦИ 			- Строка - поле поиска дублера
//    * ИдентификаторСЭП 			- Строка
//    * ШаблонПодтверждения 		- Строка
//    * ВнутреннийИдентификатор	- Строка
//    * ОграничениеАвторизации	- Строка
//    * АдресЛичногоКабинета 		- Строка
//    * Используется				- Булево
//    * ТаймАут					- Число
//    * Комментарий				- Строка
//    * ВерсияАПИ					- Строка
//
// Возвращаемое значение:
//  СправочникСсылка.ЭкземплярыСервераDSS
//
Функция ОбновитьДанныеСервераОблачнойПодписи(НастройкиСервиса) Экспорт
	
	Возврат СервисКриптографииDSSСлужебный.СоздатьСерверОблачнойПодписи(НастройкиСервиса);
	
КонецФункции

// Возвращает найденный сертификат по отбору.
//
// Параметры:
//  ОписаниеСертификата	 - Структура - с полем "Отпечаток", "СерийныйНомер" или "ИдентификаторСертификата"
//  ПараметрыОперации	 - Структура, ФиксированнаяСтруктура - позволяет указать дополнительные параметры операции, ожидаемые поля:
//    * ПолучитьДвоичныеДанные - Булево - преобразовывать двоичные данные
// 
// Возвращаемое значение:
//   см. СервисКриптографииDSSКлиентСервер.ОтветСервисаПоУмолчанию.
//
Функция НайтиСертификат(ОписаниеСертификата, ПараметрыОперации = Неопределено) Экспорт
	
	Результат = СервисКриптографииDSSКлиентСервер.ОтветСервисаПоУмолчанию(Истина);
	НашлиСертификат = Неопределено;
	ПолучитьДвоичныеДанные = СвойствоСтруктуры(ПараметрыОперации, "ПолучитьДвоичныеДанные", Ложь);
	
	Если ОписаниеСертификата.Свойство("Отпечаток") Тогда
		НашлиСертификат = СервисКриптографииDSSСлужебный.ПолучитьДанныеСертификатаПоОтпечатку(ОписаниеСертификата, Истина);
	ИначеЕсли ОписаниеСертификата.Свойство("СерийныйНомер") Тогда
		НашлиСертификат = СервисКриптографииDSSСлужебный.ПолучитьДанныеСертификатаПоСерийномуНомеру(ОписаниеСертификата, Истина);
	ИначеЕсли ОписаниеСертификата.Свойство("ИдентификаторСертификата") Тогда
		НашлиСертификат = СервисКриптографииDSSСлужебный.ПолучитьДанныеСертификатаПоИдентификаторуСертификата(ОписаниеСертификата, Истина);
	КонецЕсли;
		
	Если ТипЗнч(НашлиСертификат) = Тип("Массив") Тогда
		ТекущийСертификат = ?(НашлиСертификат.Количество() = 0, Неопределено, НашлиСертификат[0]);
	Иначе
		ТекущийСертификат = НашлиСертификат;
	КонецЕсли;
	
	Если ТекущийСертификат = Неопределено Тогда
		Результат.Выполнено = Ложь;
		СервисКриптографииDSSСлужебный.ПолучитьОписаниеОшибки(
				Результат,
				"ОшибкаВыполнения", 
				НСтр("ru = 'Сертификат не обнаружен в сервисе DSS'", СервисКриптографииDSSСлужебный.КодЯзыка()));
	Иначе
		Результат.Вставить("ДанныеСертификата", ПолучитьОбъектСертификата(ТекущийСертификат.ДанныеСертификата, Истина, НЕ ПолучитьДвоичныеДанные));
		Результат.Вставить("УчетнаяЗапись", ТекущийСертификат.УчетнаяЗапись);
		Результат.Вставить("Идентификатор", ТекущийСертификат.Идентификатор);
		Результат.Вставить("ДатаНачала", ТекущийСертификат.ДатаНачала);
		Результат.Вставить("ДатаОкончания", ТекущийСертификат.ДатаОкончания);
		Результат.Вставить("Наименование", ТекущийСертификат.Наименование);
		Результат.Вставить("Отпечаток", ТекущийСертификат.Отпечаток);
		Результат.Вставить("СерийныйНомер", ТекущийСертификат.СерийныйНомер);
		Результат.Вставить("ИдентификаторСертификата", ТекущийСертификат.ИдентификаторСертификата);
	КонецЕсли;
	
	Возврат Результат;
	
КонецФункции

// Формирует ТаблицуЗначений с данным сертификатов хранимые в кеше сертификатов.
// Данные формируется на основе закэшированных сертификатов после последней аутентификации.
//
// Параметры:
//  ВключитьСодержимоеСертификата - Булево - заполняет поле ДанныеСертификата двоичным содержимым сертификата
//
// Возвращаемое значение:
//  ТаблицаЗначений:
//    * УчетнаяЗапись		- СправочникСсылка.УчетныеЗаписиDSS
//    * Отпечаток			- Строка
//    * ДатаНачала			- Дата
//    * ДатаОкончания		- Дата
//    * ДанныеСертификата	- Неопределено
//							- ХранилищеЗначения
//
Функция ПолучитьВсеСертификатыСервиса(ВключитьСодержимоеСертификата = Истина) Экспорт
	
	Возврат СервисКриптографииDSSСлужебный.ПолучитьВсеСертификаты(ВключитьСодержимоеСертификата);
	
КонецФункции

// Функция поиска и получения ссылки учетной записи по полям поиска
//
// Параметры:
//  ПоляПоиска - Структура - содержит поля для поиска. Список полей ограничивается списком реквизитов справочника.
//
// Возвращаемое значение:
//  - Неопределено
//  - СправочникСсылка.УчетныеЗаписиDSS
//
Функция НайтиУчетнуюЗапись(ПоляПоиска) Экспорт
	
	Результат = СервисКриптографииDSSСлужебный.ПроверитьДублированиеЛогинов(Неопределено, ПоляПоиска);
	
	Возврат Результат;
	
КонецФункции

// Формирует таблицу значений с данными учетных записей.
// Данные формируется на основе закэшированных сертификатов после последней аутентификации.
//
// Параметры:
//  СсылкаСправочника 		- СправочникСсылка.УчетныеЗаписиDSS
//
// Возвращаемое значение:
//  ТаблицаЗначений:
//    * Ссылка 			- СправочникСсылка.УчетныеЗаписиDSS
//    * Владелец 			- СправочникСсылка.ЭкземплярыСервераDSS
//    * Наименование 		- Строка
//    * Логин 			- Строка
//    * ПометкаУдаления 	- Булево
//    * Сервер 			- Строка - наименование сервера
//    * ВнутреннийИдентификатор - Строка - идентификатор для поиска поставляемых данных
//
Функция ПолучитьВсеУчетныеЗаписи(СсылкаСправочника = Неопределено) Экспорт
	
	Возврат СервисКриптографииDSSСлужебный.ПолучитьВсеУчетныеЗаписи(СсылкаСправочника);
	
КонецФункции

// Возвращает таблицу содержащую все используемые серверы облачной подписи
//
// Параметры:
//  ОтборЗапроса - Неопределено, Соответствие, Структура - содержит ключи и значения отбора
//
// Возвращаемое значение:
//  ТаблицаЗначений:
//    * Ссылка 					- СправочникСсылка.ЭкземплярыСервераDSS
//    * Наименование 				- Строка
//    * АдресСервера 				- Строка
//    * АдресЛичногоКабинета 		- Строка
//    * СервисИдентификации 		- Строка
//    * СервисПодписи 			- Строка
//    * СервисПроверки 			- Строка
//    * СервисАудита	 			- Строка
//    * СервисСервисДокументов	- Строка
//    * ВнутреннийИдентификатор 	- Строка - необходим для поиска информации по поставляемым серверам
//    * ИдентификаторЦИ			- Строка
//    * ИдентификаторСЭП			- Строка
//    * ШаблонПодтверждения		- Строка
//    * ВерсияАПИ					- Строка
//    * ТаймАут					- Число
//
Функция ПолучитьВсеСерверы(ОтборЗапроса = Неопределено) Экспорт
	
	Возврат СервисКриптографииDSSСлужебный.ПолучитьВсеСерверы(ОтборЗапроса);
	
КонецФункции

// Сервисная функция, позволяющая определить учетную запись сервиса по сертификата
//
// Параметры:
//  ДанныеСертификата 	- Строка - значение отпечатка сертификата
//                    	- Структура - содержит обязательное поле "Отпечаток", "СерийныйНомер" или "ИдентификаторСертификата"
//  ПараметрыОперации	- Структура, ФиксированнаяСтруктура - позволяет указать дополнительные параметры операции.
//
// Возвращаемое значение:
//   см. НастройкиПользователяПоУмолчанию
//
Функция ПолучитьНастройкиПользователяПоСертификату(ДанныеСертификата, ПараметрыОперации = Неопределено) Экспорт
	
	Если ТипЗнч(ДанныеСертификата) <> Тип("Структура") Тогда
		СвойстваСертификата = Новый Структура("Отпечаток", ДанныеСертификата);
	Иначе
		СвойстваСертификата = ДанныеСертификата;
	КонецЕсли;
	
	НашлиСертификат = НайтиСертификат(СвойстваСертификата);
	
	Если НашлиСертификат.Выполнено Тогда
		Результат = ПолучитьНастройкиПользователя(НашлиСертификат.УчетнаяЗапись, ПараметрыОперации);
	Иначе
		Результат = НастройкиПользователяПоУмолчанию();
	КонецЕсли;
	
	Возврат Результат;
	
КонецФункции

// Вспомогательная функция формирования структуры сертификата подобной объекту СертификатКриптографии, 
// с дополнительными полями. Предусмотрена для универсальной передачи информации о сертификате между 
// сервером и клиентом.
//
// Параметры:
//  ДанныеСертификата 		- ДвоичныеДанные - данные сертификата
//  ВычислитьИдентификатор 	- Булево - дополняет структуру вычисленным идентификатором
//  ДвоичныеДанныеКакHEX 	- Булево - режим преобразования двоичных данных
//
// Возвращаемое значение:
//  Структура - содержит аналогичные поля объекта платформы и дополнительные поля:
//    * Сертификат		- ДвоичныеДанные - содержимое сертификата 
//    * Идентификатор	- Строка
//    * ДействителенС	- Дата
//    * ДействителенПо 	- Дата
//    * СерийныйНомер	- Строка
//    					- ДвоичныеДанные
//    * Отпечаток		- Строка
//    					- ДвоичныеДанные
//
Функция ПолучитьОбъектСертификата(ДанныеСертификата, ВычислитьИдентификатор = Ложь, ДвоичныеДанныеКакHEX = Истина) Экспорт
	
	ОбъектСертификата	= Новый СертификатКриптографии(ДанныеСертификата);
	РасширенныеСвойства	= СервисКриптографииDSSASNКлиентСервер.ПолучитьСвойстваСертификата(ДанныеСертификата);
	
	СвойстваСертификата = Новый Структура;
	СвойстваСертификата.Вставить("Версия",						ОбъектСертификата.Версия);
	СвойстваСертификата.Вставить("ДатаНачала",					ОбъектСертификата.ДатаНачала);
	СвойстваСертификата.Вставить("ДатаОкончания",				ОбъектСертификата.ДатаОкончания);
	СвойстваСертификата.Вставить("Издатель",					ОбъектСертификата.Издатель);
	СвойстваСертификата.Вставить("ИспользоватьДляПодписи",		ОбъектСертификата.ИспользоватьДляПодписи);
	СвойстваСертификата.Вставить("ИспользоватьДляШифрования", 	ОбъектСертификата.ИспользоватьДляШифрования);
	СвойстваСертификата.Вставить("ОткрытыйКлюч",				ОбъектСертификата.ОткрытыйКлюч);
	СвойстваСертификата.Вставить("Отпечаток",					ОбъектСертификата.Отпечаток);
	СвойстваСертификата.Вставить("РасширенныеСвойства",			ОбъектСертификата.РасширенныеСвойства);
	СвойстваСертификата.Вставить("СерийныйНомер",				ОбъектСертификата.СерийныйНомер);
	СвойстваСертификата.Вставить("Субъект",						ОбъектСертификата.Субъект);
	СвойстваСертификата.Вставить("Наименование",				СвойствоСтруктуры(ОбъектСертификата.Субъект, "CN", ""));
	СвойстваСертификата.Вставить("Сертификат",					ДанныеСертификата);
	Если ВычислитьИдентификатор Тогда
		СвойстваСертификата.Вставить("Идентификатор",			СервисКриптографииDSSСлужебный.ВычислитьИдентификаторСертификата(ОбъектСертификата));
	Иначе
		СвойстваСертификата.Вставить("Идентификатор",			"");
	КонецЕсли;	
	
	// для совместимости
	СвойстваСертификата.Вставить("ДействителенС", ОбъектСертификата.ДатаНачала);
	СвойстваСертификата.Вставить("ДействителенПо", ОбъектСертификата.ДатаОкончания);
	СвойстваСертификата.Вставить("ИдентификаторСубъекта", РасширенныеСвойства.ИдентификаторСубъекта);
	
	Если ДвоичныеДанныеКакHEX Тогда
		СвойстваСертификата.СерийныйНомер = НРег(ПолучитьHexСтрокуИзДвоичныхДанных(СвойстваСертификата.СерийныйНомер));
		СвойстваСертификата.Отпечаток = НРег(ПолучитьHexСтрокуИзДвоичныхДанных(СвойстваСертификата.Отпечаток));
	КонецЕсли;
	
	Возврат Новый ФиксированнаяСтруктура(СвойстваСертификата);
	
КонецФункции

// Функция формирует структуру (объект) описывающая сессионные данные учетной записи.
//
// Возвращаемое значение:
//  Структура - содержит поля настроек пользователя:
//    * ВерсияАПИ					- Строка - номер сборки сервера DSS
//    * ПризнакКонфиденциальности	- Число - способ формирования конфиденциальных данных
//    * ТокенАвторизации			- Структура
//    * Ссылка						- СправочникСсылка.УчетныеЗаписиDSS - ссылка на справочник учетной записи, для которой сформированы сессионные данные
//    * Сервер						- СправочникСсылка.ЭкземплярыСервераDSS - ссылка на справочник сервера к которой привязана учетная запись
//    * УникальныйИдентификатор		- Строка - уникальный идентификатор ссылки
//    * ИдентификаторНаСервере		- Строка - уникальный идентификатор учетной записи присвоенный сервером облачной подписи
//    * Логин						- Строка
//    * Пароль						- Строка
//    								- Структура
//    * ПарольСертификата			- Строка 
//    								- Структура
//    * СертификатАвторизации		- Булево - информация о наличии сертификата авторизации
//    * Телефон						- Строка - номер телефона полученный в момент авторизации
//    * ЭлектроннаяПочта			- Строка - адрес электронной почты полученный в момент авторизации
//    * ПервичнаяАутентификация		- ПеречислениеСсылка.СпособыАвторизацииDSS - основной способ авторизации (4 способа)
//    * ВторичнаяАвторизация		- ПеречислениеСсылка.СпособыАвторизацииDSS - основной способ подтверждения операций
//    * Политика					- см. НастройкиПолитикиПользователяПоУмолчанию
//    * Подключение					- Структура - данные для подключения к серверу, см. подробнее НастройкиРаботыПодключение()
//    * Методы						- Структура - данные для вызова операций на сервере, см. подробнее НастройкиРаботыТочкиПодключения()
//    * Сертификаты					- Соответствие из КлючИЗначение -  список сертификатов учетной записи:
//      ** Ключ						- Строка
//      ** Значение					- см. СервисКриптографииDSSКлиентСервер.СвойстваСертификатаПользователя
//    * ШаблонПодтверждения 		- Строка - идентификатор шаблона для произвольного подтверждения
//    * ВерсияНастройки 			- Число - счетчик при количества записей в параметры сеанса
//    * АвторизованныйПользователь	- Строка - уникальный идентификатор пользователя 1С
//    * ЗапоминатьПароли			- Булево - признак необходимости хранения введенных паролей в параметрах сеанса
//    * ДанныеБД					- Булево - признак наличия зарегистрированного пользователя
//    * НеудачныхПопыток			- Число - количество подряд неудачных попыток авторизоваться
//
Функция НастройкиПользователяПоУмолчанию() Экспорт
	
	Возврат СервисКриптографииDSSСлужебный.НастройкиПользователяПоУмолчанию();
	
КонецФункции

// Формирует данные для хранения политик работы пользователя.
//
// Возвращаемое значение:
//  Структура:
//    * Заполнено			- Булево - признак, что произошла удачная авторизация и получены настройки учетной записи с сервера
//    * ДатаЗаполнения		- Дата - когда были заполнены настройки
//    * Действия			- Структура из КлючИЗначение - содержит список действий, которые допустимы для пользователя и признак подтверждения:
//      ** Ключ				- Строка
//      ** Значение			- Структура:
//        *** Ключ			- Строка - код операции
//        *** Подтверждать	- Булево
//    * УЦ					- Массив из Структура:
//      ** Имя				- Строка - представление УЦ
//      ** Идентификатор	- Строка - внутренний идентификатор УЦ на сервере DSS
//      ** Сторонний		- Булево - сторонний УЦ, требует отдельной операции установки сертификата
//      ** Шаблоны			- Массив из Структура:
//        *** Наименование	- Строка
//        *** Шаблон		- Строка - OID шаблона
//      ** ИменаПолей		- Массив из Структура:
//        *** OID			- Строка - идентификатор поля
//        *** IsRequired	- Булево - Истина, если поле обязательно для заполнения
//    * Криптопровайдеры	- Массив из Структура:
//      ** Идентификатор	- Строка - GUID криптопровайдера на сервере DSS
//      ** Описание 		- Строка - представление криптопровайдера
//      ** Тип		 		- Число - тип криптопровайдера
//      ** Имя		 		- Строка - имя криптопровайдера
//    * СервераШтамповВремени- Массив из Структура:
//      ** Имя				- Строка - представление сервера
//      ** Адрес			- Строка - Web-адрес службы штампа времени
//    * ТипыПодписей		-  Массив из Число - идентификаторы типов подписи
//    * РежимПинКода		- Строка - строковая константа режим применения пин-кодов для сертификатов варианты: Обязательно, Запрещено, Опционально.
//
Функция НастройкиПолитикиПользователяПоУмолчанию() Экспорт
	
	Результат = Новый Структура;
	Результат.Вставить("Заполнено", Ложь);
	Результат.Вставить("ДатаЗаполнения", '00010101');
	Результат.Вставить("Действия", Новый Структура);
	Результат.Вставить("УЦ", Новый Массив);
	Результат.Вставить("Криптопровайдеры", Новый Массив);
	Результат.Вставить("СервераШтамповВремени", Новый Массив);
	Результат.Вставить("РежимПинКода", "Опционально");
	
	Возврат Результат;
	
КонецФункции

// Получает картинку используемую в подсистеме, если не найдена то будет пустая картинка
//
// Параметры:
//  ИмяКартинки - Строка
//
// Возвращаемое значение:
//  Картинка
//
Функция ПолучитьКартинкуПодсистемы(ИмяКартинки) Экспорт
	
	ИщемКартинку = Новый Структура(ИмяКартинки);
	Результат = Неопределено;
	
	Попытка 
		ЗаполнитьЗначенияСвойств(ИщемКартинку, БиблиотекаКартинок);
		ИщемКартинку.Свойство(ИмяКартинки, Результат);
	Исключение
		Результат = Новый Картинка;
	КонецПопытки;
	
	Если Результат = Неопределено Тогда
		Результат = Новый Картинка;
	КонецЕсли;
	
	Возврат Результат;
	
КонецФункции

// Проверяет заполнение значения СлужебнаяУчетнаяЗаписьDSS.
// Формирует структуру необходимую для подключения к серверу DSS.
//
// Возвращаемое значение:
//   см. СервисКриптографииDSSКлиентСервер.ОтветСервисаПоУмолчанию
//
Функция НастройкиПодключенияСлужебнойУчетнойЗаписи() Экспорт
	
	ТекстОшибки = "";
	НастройкиСервера = ПолучитьОписаниеСервисаDSS();
	НастройкиСервера.Вставить("Логин", "");
	НастройкиСервера.Вставить("Пароль", "");
	
	ИмяНастроек = СервисКриптографииDSSСлужебный.ИмяНастроекСлужебнойУчетнойЗаписи();
	
	УстановитьПривилегированныйРежим(Истина);
	
	СодержимоеНастроек = ОбщегоНазначения.ПрочитатьДанныеИзБезопасногоХранилища(ИмяНастроек, "Настройки", Истина);
	
	УстановитьПривилегированныйРежим(Ложь);
	
	Если ТипЗнч(СодержимоеНастроек) = Тип("Строка") Тогда
		Попытка
			СодержимоеНастроек = ОбщегоНазначения.JSONВЗначение(СодержимоеНастроек, , Ложь);
		Исключение
			СодержимоеНастроек = Неопределено;
		КонецПопытки;
	КонецЕсли;
	
	Если ТипЗнч(СодержимоеНастроек) <> Тип("Структура") Тогда
		ТекстОшибки = НСтр("ru = 'Не установлены настройки служебной учетной записи'");
	Иначе
		ЗаполнитьЗначенияСвойств(НастройкиСервера, СодержимоеНастроек);
		Если НЕ (ЗначениеЗаполнено(НастройкиСервера.Ссылка)
			ИЛИ (ЗначениеЗаполнено(НастройкиСервера.АдресСервера)
			И ЗначениеЗаполнено(НастройкиСервера.СервисИдентификации)
			И ЗначениеЗаполнено(НастройкиСервера.СервисПодписи)
			И ЗначениеЗаполнено(НастройкиСервера.СервисПроверки))) Тогда
			ТекстОшибки = НСтр("ru = 'Не заданы необходимые настройки подключения'");
		КонецЕсли;
		
		Если НЕ ЗначениеЗаполнено(НастройкиСервера.Логин) Тогда
			ТекстОшибки = НСтр("ru = 'Не задан логин служебной учетной записи'");
		КонецЕсли;
		
	КонецЕсли;
	
	Если ЗначениеЗаполнено(ТекстОшибки) Тогда
		Результат = СервисКриптографииDSSКлиентСервер.ОтветСервисаПоУмолчанию(Ложь);
		СервисКриптографииDSSСлужебный.ПолучитьОписаниеОшибки(Результат, "ОшибкаВыполнения", ТекстОшибки);
	Иначе
		НастройкиПользователя = НастройкиПроизвольногоПодключения(НастройкиСервера, 
								НастройкиСервера.Логин,
								НастройкиСервера.Пароль);
		Результат = СервисКриптографииDSSКлиентСервер.ОтветСервисаПоУмолчанию(Истина);
		Результат.Вставить("Результат", НастройкиПользователя);
	КонецЕсли;
	
	Возврат Результат;
	
КонецФункции

// Формирует структуру необходимую для подключения к серверу DSS.
// Необходим в случае использования служебных учетных записей.
//
// Параметры:
//  НастройкиСервера 	- Структура
//  ЛогинУчетнойЗаписи	- Строка
//  ПарольУчетнойЗаписи	- Строка
//  СпособАвторизации	- Неопределено
//                   	- ПеречислениеСсылка.СпособыАвторизацииDSS
//
// Возвращаемое значение:
//   см. НастройкиПользователяПоУмолчанию
//
Функция НастройкиПроизвольногоПодключения(НастройкиСервера, ЛогинУчетнойЗаписи, ПарольУчетнойЗаписи = "", СпособАвторизации = Неопределено) Экспорт
	
	НастройкиПользователя = Неопределено;
	
	СервисКриптографииDSSПодтверждениеСервер.ДополнитьНастройкиПользователя(НастройкиПользователя, НастройкиСервера, ЛогинУчетнойЗаписи);
	НастройкиПользователя.Пароль = СервисКриптографииDSSКлиентСервер.ОбъектПароля(ПарольУчетнойЗаписи);
	Если ЗначениеЗаполнено(СпособАвторизации) Тогда
		НастройкиПользователя.ПервичнаяАутентификация = СпособАвторизации;
	Иначе
		НастройкиПользователя.ПервичнаяАутентификация = Перечисления.СпособыАвторизацииDSS.Первичный_УчетныеДанные;
	КонецЕсли;
	
	Возврат НастройкиПользователя;
	
КонецФункции

// Формирует шаблон для заполнения информации о сервере DSS
//
// Возвращаемое значение:
//   Структура
//
Функция ПолучитьОписаниеСервисаDSS() Экспорт
	
	Результат = Новый Структура;
	Результат.Вставить("Ссылка", Новый(СервисКриптографииDSSКлиентСервер.ПолучитьТипСервераОблачнойПодписи()));
	Результат.Вставить("Наименование", "");
	Результат.Вставить("АдресСервера", "");
	Результат.Вставить("АдресЛичногоКабинета", "");
	Результат.Вставить("СервисИдентификации", "");
	Результат.Вставить("СервисПодписи", "");
	Результат.Вставить("СервисПроверки", "");
	Результат.Вставить("СервисОбработкиДокументов", "");
	Результат.Вставить("СервисАудита", "");
	Результат.Вставить("ВнутреннийИдентификатор", "");
	Результат.Вставить("ИдентификаторЦИ", "");
	Результат.Вставить("ИдентификаторСЭП", "");
	Результат.Вставить("ШаблонПодтверждения", "");
	Результат.Вставить("ТаймАут", 120);
	Результат.Вставить("ВерсияАПИ", "");
	Результат.Вставить("Комментарий", "");
	Результат.Вставить("Используется", Истина);
	Результат.Вставить("ОграничениеАвторизации", "");
	
	Возврат Результат;
	
КонецФункции

#КонецОбласти

#Область ПоддержкаВнешнегоСоединения

// Формирует для внешнего потребителя список настроек пользователя сервиса.
// Для корректной работы, требуется предварительная аутентификация.
//
// Параметры:
//  ИдентификаторПользователя 	- Структура, СправочникСсылка.УчетныеЗаписиDSS - см. функцию НастройкиПользователяПоУмолчанию()
//  ПараметрыОперации 			- Структура, ФиксированнаяСтруктура - позволяет указать дополнительные параметры операции:
//    * ДатаСеанса 			- Дата
//    * ИсточникНастроек 		- Строка
//
// Возвращаемое значение:
//   см. СервисКриптографииDSSКлиентСервер.ОтветСервисаПоУмолчанию
//
Функция ПолучитьПолитикуНастроек(ИдентификаторПользователя, ПараметрыОперации = Неопределено) Экспорт
	
	НастройкиПользователя = ПолучитьНастройкиПользователя(ИдентификаторПользователя, ПараметрыОперации);
	Результат = СервисКриптографииDSSСлужебный.ПолучитьПолитикуНастроек(НастройкиПользователя);
	
	Возврат Результат;
	
КонецФункции

// Подготавливает транзакцию для выполнения операции.
// Поддерживаемые операции: Подписание, Расшифровка, Аутентификация
// При необходимости проводит первичную аутентификацию или обновляет маркер безопасности.
//
// Параметры:
//  ИдентификаторПользователя 	- Структура, СправочникСсылка.УчетныеЗаписиDSS - см. функцию НастройкиПользователяПоУмолчанию()
//  ТипОперации					- Строка - идентификатор операции
//  ПараметрыОперации 			- Структура - позволяет указать параметры в зависимости от типа операции:
//      * ИсточникНастроек		- Строка - способ получения сеансовых данных.
//      * Пароль				- Строка - пароль для авторизации, для операции аутентификации обязателен.
//      * ДатаСеанса			- Дата - дата авторизации
//      * ОжидатьВыборСпособа	- Булево - выбор способа подтверждения.
//		
//		Для Расшифровка.
//      * ДанныеДокумента 		- Массив из Структура:
//        ** Ссылка				- Произвольный - ключ для сопоставления результатов
//        ** Содержание			- ДвоичныеДанные, Строка - один файл, который необходимо обработать
//        ** ИмяДокумента			- Строка - представление документа
//        ** ТипДокумента			- Строка - тип документа (расширение файла)
//      * Отпечаток 			- Строка - опционально
//      * ПинКод 				- Строка - опционально
//		
//		Для Подпись.
//      * ДанныеДокумента		- Массив из Структура - подробное описание в разделе Расшифровка (выше)
//      * Отпечаток				- Строка
//      * ПинКод				- Строка - опционально
//
// Возвращаемое значение:
//   см. СервисКриптографииDSSКлиентСервер.ОтветСервисаПоУмолчанию
//	
Функция ПодготовитьТранзакцию(ИдентификаторПользователя, ТипОперации, ПараметрыОперации = Неопределено) Экспорт
	
	НастройкиПользователя = ПолучитьНастройкиПользователя(ИдентификаторПользователя, ПараметрыОперации);
	Результат = СервисКриптографииDSSСлужебный.ПодготовитьТранзакциюПодтверждения(НастройкиПользователя, ТипОперации, ПараметрыОперации);
	
	Возврат Результат;
	
КонецФункции

// Возвращает текущий статус ранее созданной операции с подтверждением.
// При необходимости проводит первичную аутентификацию или обновляет маркер безопасности.
//
// Параметры:
//  ИдентификаторПользователя 	- Структура, СправочникСсылка.УчетныеЗаписиDSS - см. функцию НастройкиПользователяПоУмолчанию()
//  ИдентификаторТранзакции		- Неопределено, Строка - контролирует соответствие ожидаемой операции
//  ПараметрыОперации 			- Структура, ФиксированнаяСтруктура - позволяет указать параметры в зависимости от типа операции
//
// Возвращаемое значение:
//   см. СервисКриптографииDSSКлиентСервер.ОтветСервисаПоУмолчанию
//	
Функция ПолучитьСтатусПодтверждения(ИдентификаторПользователя, ИдентификаторТранзакции = Неопределено, ПараметрыОперации = Неопределено) Экспорт
	
	НастройкиПользователя = ПолучитьНастройкиПользователя(ИдентификаторПользователя, ПараметрыОперации);
	Результат = СервисКриптографииDSSСлужебный.ПолучитьСтатусПодтверждения(НастройкиПользователя, ИдентификаторТранзакции, ПараметрыОперации);
	
	Возврат Результат;
	
КонецФункции

// Для изменения состояния ранее созданной операции с подтверждением.
//
// Параметры:
//  ИдентификаторПользователя	- СправочникСсылка.УчетныеЗаписиDSS
//                           	- Структура - см. функцию НастройкиПользователяПоУмолчанию()
//  ТипОперации					- Строка - идентификатор операции из возможных "ВременныйКод", "ВыборСпособа"
//  НовоеЗначение				- Строка 
//               				- Число
//  ИдентификаторТранзакции		- Неопределено, Строка - контролирует соответствие ожидаемой операции
//  ПараметрыОперации 			- Структура, ФиксированнаяСтруктура - позволяет указать параметры в зависимости от типа операции
//
// Возвращаемое значение:
//   см. СервисКриптографииDSSКлиентСервер.ОтветСервисаПоУмолчанию
//	
Функция ИзменитьСтатусПодтверждения(ИдентификаторПользователя, ТипОперации, НовоеЗначение, ИдентификаторТранзакции = Неопределено, ПараметрыОперации = Неопределено) Экспорт
	
	НастройкиПользователя = ПолучитьНастройкиПользователя(ИдентификаторПользователя, ПараметрыОперации);
	Результат = СервисКриптографииDSSСлужебный.ИзменитьСтатусПодтверждения(
								НастройкиПользователя,
								ИдентификаторТранзакции,
								ТипОперации,
								НовоеЗначение,
								ПараметрыОперации);
	
	Возврат Результат;
	
КонецФункции

// Получает результат после подтверждения операций расшифровки или подписи.
//
// Параметры:
//  ИдентификаторПользователя 	- Структура, СправочникСсылка.УчетныеЗаписиDSS - см. функцию НастройкиПользователяПоУмолчанию()
//  ИдентификаторТранзакции		- Неопределено, Строка - контролирует соответствие ожидаемой операции
//  ПараметрыОперации 			- Структура, ФиксированнаяСтруктура - позволяет указать параметры в зависимости от типа операции
//
// Возвращаемое значение:
//   см. СервисКриптографииDSSКлиентСервер.ОтветСервисаПоУмолчанию
//	
Функция ПолучитьРезультатПодтверждения(ИдентификаторПользователя, ИдентификаторТранзакции = Неопределено, ПараметрыОперации = Неопределено) Экспорт
	
	НастройкиПользователя = ПолучитьНастройкиПользователя(ИдентификаторПользователя, ПараметрыОперации);
	Результат = СервисКриптографииDSSСлужебный.ПолучитьРезультатПодтверждения(НастройкиПользователя, ИдентификаторТранзакции, ПараметрыОперации);
	
	Возврат Результат;
	
КонецФункции

// Сохраняет закрытые данные пароли, пин-коды пользователя сервиса.
//
// Параметры:
//  ИдентификаторПользователя 	- Структура, СправочникСсылка.УчетныеЗаписиDSS - см. функцию НастройкиПользователяПоУмолчанию()
//  ИмяПараметра				- Строка - идентификатор сохраняемого значения
//  ЗначениеПараметра			- Строка, Структура - см. СервисКриптографииDSSКлиентСервер.ОбъектПароля
//  ПараметрыОперации 			- Структура, ФиксированнаяСтруктура - позволяет указать параметры в зависимости от типа операции
//
// Возвращаемое значение:
//   см. СервисКриптографииDSSКлиентСервер.ОтветСервисаПоУмолчанию
//
Функция СохранитьЗакрытыеДанныеПользователя(ИдентификаторПользователя, ИмяПараметра, ЗначениеПараметра, ПараметрыОперации = Неопределено) Экспорт
	
	Результат = СервисКриптографииDSSКлиентСервер.ОтветСервисаПоУмолчанию(Ложь);
	
	НастройкиПользователя = ПолучитьНастройкиПользователя(ИдентификаторПользователя, ПараметрыОперации);
	Если ЗначениеЗаполнено(НастройкиПользователя.Логин) Тогда
		Результат = СервисКриптографииDSSСлужебный.СохранитьЗакрытыеДанныеПользователя(НастройкиПользователя,
											ИмяПараметра,
											ЗначениеПараметра,
											ПараметрыОперации);
	КонецЕсли;
	
	Возврат Результат;
	
КонецФункции

#КонецОбласти

#КонецОбласти

#КонецОбласти

#Область СлужебныеПроцедурыИФункции

// Функция предназначена для обобщения двух функций: создание подключения и вызов функции API.
// При подключении к серверу проверяется актуальность токена и по возможности он обновляется.
// Также функция автоматически формирует заголовок авторизации пользователя.
// 
// Параметры:
//   ИдентификаторПользователя	- см. НастройкиПользователяПоУмолчанию
//  АдресМетода					- Строка - точка подключения к сервису
//  ПараметрыМетода 			- Структура - содержит параметры передаваемые в метод вызова HTTP-запрос
//  МетодHTTP					- Строка - содержит метод вызова: GET, POST и прочие методы.
//   ТипСодержания				- Строка - указывает как формировать тело запроса из ПараметрыМетода, поддерживаются варианты:
//									octet: передать двоичными данными,
//									text: передать структуру как форматированную строку,
//									json_list: передать как json и вернуть как Соответствие,
//									json: передать как json.
//  Заголовки 					- Структура, Соответствие - передается как параметр в объект HTTP-запрос
//  ПараметрыОперации 			- Структура, ФиксированнаяСтруктура - позволяет указать дополнительные параметры операции.
//
// Возвращаемое значение:
//   см. СервисКриптографииDSSКлиентСервер.ОтветСервисаПоУмолчанию
//
Функция ПодключитьВыполнитьМетодСервиса(
								ИдентификаторПользователя,
								АдресМетода, 
								ПараметрыМетода, 
								МетодHTTP, 
								ТипСодержания = "text",
								Заголовки = Неопределено,
								ПараметрыОперации = Неопределено) Экспорт
								
	НастройкиПользователя	= ПолучитьНастройкиПользователя(ИдентификаторПользователя, ПараметрыОперации);
	Если НастройкиПользователя = Неопределено Тогда
		РезультатЗапроса = СервисКриптографииDSSКлиентСервер.ОтветСервисаПоУмолчанию(Ложь);
		СервисКриптографииDSSСлужебный.ПолучитьОписаниеОшибки(РезультатЗапроса, "Пользователь");
		Возврат РезультатЗапроса;
	КонецЕсли;
	
	СвойстваПодключения	= СервисКриптографииDSSСлужебный.ПодготовитьСвойстваПодключения(НастройкиПользователя.Подключение, АдресМетода);
	Соединение 			= СервисКриптографииDSSСлужебный.ПодготовитьПодключение(СвойстваПодключения, Неопределено, ПараметрыОперации);
	
	Если НЕ Соединение.Выполнено Тогда
		Возврат Соединение;
	КонецЕсли;
	
	Если Заголовки = Неопределено Тогда
		Заголовки = Новый Соответствие;
	КонецЕсли;
	
	ОбновилиТокен 		= Ложь;
	ТребуетАвторизации	= СвойствоСтруктуры(ПараметрыОперации, "ТребуетАвторизации", Истина);
	
	Для Счетчик = 1 По 2 Цикл
		// проверим на валидность токен авторизации
		Если ТребуетАвторизации Тогда
			РезультатАвторизации = ПроверитьТокенАутентификации(НастройкиПользователя, Счетчик = 2, ПараметрыОперации);
			ОбновилиТокен = ОбновилиТокен ИЛИ РезультатАвторизации.МаркерОбновлен;
			Токен = ПолучитьЗначениеПароля(НастройкиПользователя.ТокенАвторизации.Токен, НастройкиПользователя);
			Если ЗначениеЗаполнено(НастройкиПользователя.ТокенАвторизации.ТипТокена) Тогда
				Заголовки.Вставить("Authorization", НастройкиПользователя.ТокенАвторизации.ТипТокена + " " + Токен);
			КонецЕсли;
		КонецЕсли;
		РезультатЗапроса = СервисКриптографииDSSСлужебный.ВыполнитьМетодСервиса(Соединение, СвойстваПодключения.АдресПодключения, ПараметрыМетода, МетодHTTP, Заголовки, ТипСодержания, ПараметрыОперации);
		Если РезультатЗапроса.Выполнено ИЛИ НЕ СервисКриптографииDSSКлиентСервер.ЭтоОшибкаАутентификации(РезультатЗапроса.Ошибка) Тогда
			Прервать;
		КонецЕсли;	
	КонецЦикла;
	
	Если ОбновилиТокен Тогда
		РезультатЗапроса.Вставить("НастройкиПользователя", НастройкиПользователя);
	КонецЕсли;	
	РезультатЗапроса.МаркерОбновлен = ОбновилиТокен;
	
	Если РезультатЗапроса.Свойство("Заголовки") Тогда
		РезультатЗапроса.Удалить("Заголовки");
	КонецЕсли;
	
	Возврат РезультатЗапроса;
	
КонецФункции	

// Служебная функция для обновления токена учетной записи на стороне сервера.
// способами которые возможные не использовать интерактивное взаимодействие с пользователем.
//
// Параметры:
//  НастройкиПользователя 	- см. НастройкиПользователяПоУмолчанию
//  Принудительно 			- Булево - обновить токен не обращая внимания на срок действия.
//  Авторизован				- Булево - текущий статус авторизации учетной записи.
//  ПараметрыОперации 		- Структура - позволяет указать дополнительные параметры операции:
//    * ДатаСеанса		- Дата
//    * ИсточникНастроек	- Строка
//
// Возвращаемое значение:
//  Булево 					- Истина, если успешно обновился маркер безопасности
//
Функция ПроверитьТокенАутентификации(НастройкиПользователя, Принудительно, ПараметрыОперации = Неопределено)
	
	ДатаСеанса = СервисКриптографииDSSСлужебный.ДатаСеанса();
	ДатаСеанса = СвойствоСтруктуры(ПараметрыОперации, "ДатаСеанса", ДатаСеанса);
	Авторизован = Ложь;
	
	Токен = ПолучитьЗначениеПароля(НастройкиПользователя.ТокенАвторизации.Токен, НастройкиПользователя);
	ТокенОбновления = ПолучитьЗначениеПароля(НастройкиПользователя.ТокенАвторизации.ТокенОбновления, НастройкиПользователя);
	
	Если ЗначениеЗаполнено(Токен)
		И НастройкиПользователя.ТокенАвторизации.СрокДействия >= ДатаСеанса Тогда
		Авторизован = Истина;
	КонецЕсли;
	
	Результат = СервисКриптографииDSSКлиентСервер.ОтветСервисаПоУмолчанию(Авторизован);
	
	// проверим на валидность токена подключения
	Если (НЕ Авторизован ИЛИ Принудительно)
		И ЗначениеЗаполнено(ТокенОбновления) Тогда
		Результат = ОбновитьТокенАутентификации(НастройкиПользователя, ПараметрыОперации);
		Авторизован = Результат.Выполнено;
	КонецЕсли;
	
	Если НЕ Авторизован ИЛИ Принудительно Тогда
		
		ВидАутентификации = НастройкиПользователя.ПервичнаяАутентификация;
		
		Если ВидАутентификации = Перечисления.СпособыАвторизацииDSS.Первичный_УчетныеДанные 	// основной сценарий
			ИЛИ ВидАутентификации = Перечисления.СпособыАвторизацииDSS.Первичный_ДвухФакторная 		// возможно, если не подтверждается выпуск маркера безопасности
			ИЛИ ВидАутентификации = Перечисления.СпособыАвторизацииDSS.Первичный_КодАвторизации Тогда // возможно, если не подтверждается выпуск маркера безопасности
			Результат = АутентификацияПоЛогину(НастройкиПользователя, ПараметрыОперации);
		ИначеЕсли ВидАутентификации = Перечисления.СпособыАвторизацииDSS.Первичный_СертификатАвторизации Тогда
			Результат = АутентификацияПоСертификату(НастройкиПользователя, ПараметрыОперации);
		КонецЕсли;
		
	КонецЕсли;	
	
	Возврат Результат;
	
КонецФункции

// Функция подготавливает массив сертификатов в двоичном виде для операции шифрования
//
// Параметры:
//  - Сертификаты 	- Массив, ФиксированныйМассив, Структура, ДвоичныеДанные - содержит данные сертификатов
//
// Возвращаемое значение:
//  Массив - содержит элементы с двоичными данными
//
Функция ПолучитьДвоичныеДанныеСертификатов(Сертификаты)
	
	Результат = Новый Массив;
	
	Если ТипЗнч(Сертификаты) = Тип("Массив") ИЛИ ТипЗнч(Сертификаты) = Тип("ФиксированныйМассив") Тогда
		МассивСертификатов = Сертификаты;
	Иначе
		МассивСертификатов = Новый Массив;
		МассивСертификатов.Добавить(Сертификаты);
	КонецЕсли;
	
	Попытка 
		Для Каждого Сертификат Из МассивСертификатов Цикл
			ДанныеСертификата = ПолучитьСодержимоеСертификата(Сертификат);
			Если ЗначениеЗаполнено(ДанныеСертификата) Тогда
				Результат.Добавить(ДанныеСертификата);	
			КонецЕсли;	
		КонецЦикла;
		
	Исключение
		Результат = Новый Массив;
		
	КонецПопытки;	
	
	Возврат Результат;
	
КонецФункции

// Служебная функция для получения двоичных данных сертификата (содержимое)
//
// Параметры:
//  Сертификат - ДвоичныеДанные, Структура, ФиксированнаяСтруктура - если структура содержит поле "Сертификат", 
//				то это поле преобразуется в двоичные данные, иначе структура должна содержать поля
//				Отпечаток или Издатель с последующим поиском в регистре СертификатыПользователяDSS.
//
Функция ПолучитьСодержимоеСертификата(Сертификат)
	
	Результат = Неопределено;
	
	Если ТипЗнч(Сертификат) = Тип("ДвоичныеДанные") Тогда
		Результат = СервисКриптографииDSSКлиентСервер.СертификатВКодировкеDER(Сертификат);
	ИначеЕсли (ТипЗнч(Сертификат) = Тип("Структура") ИЛИ ТипЗнч(Сертификат) = Тип("ФиксированнаяСтруктура"))
		И Сертификат.Свойство("Сертификат") Тогда
		Результат = СервисКриптографииDSSКлиентСервер.СертификатВКодировкеDER(Сертификат.Сертификат);
	Иначе
		НашлиСертификат = НайтиСертификат(Сертификат);
		Если НашлиСертификат.Выполнено Тогда
			Результат = НашлиСертификат.ДанныеСертификата;
		КонецЕсли;	
	КонецЕсли;
	
	Если ЗначениеЗаполнено(Результат) Тогда
		Результат = Base64Строка(Результат);
	КонецЕсли;	
	
	Возврат Результат;
	
КонецФункции

// Служебная функция для подготовки входящих параметров для формирования запросов к серверу
// 
// Параметры:
//  НастройкиПользователя		- Структура - см. подробнее НастройкиПользователяПоУмолчанию
//  ПараметрыОперации 			- Структура, ФиксированнаяСтруктура - позволяет указать дополнительные параметры операции. Проверяемые поля:
//    * ИсточникНастроек		- Строка - допустимо два варианта определенные в функциях
//								СервисКриптографииDSSКлиентСервер.ИсточникНастроекПараметрыСеанса (по-умолчанию),
//								СервисКриптографииDSSКлиентСервер.ИсточникНастроекХранилище.
//
// Возвращаемое значение:
//   см. НастройкиПользователяПоУмолчанию
//
Функция ПолучитьНастройкиПользователя(НастройкиПользователя, ПараметрыОперации = Неопределено)
	
	Результат = НастройкиПользователя;
	Если НастройкиПользователя = Неопределено Тогда
		Результат = СервисКриптографииDSSСлужебный.ПолучитьНастройкиПользователя();
	ИначеЕсли ТипЗнч(НастройкиПользователя)	<> Тип("Структура") Тогда
		ВходящиеПараметры = ПроверитьПараметрыОперации(ПараметрыОперации);
		ИсточникНастроек = СервисКриптографииDSSСлужебный.ПолучитьИсточникНастроек(ВходящиеПараметры);
		Результат = СервисКриптографииDSSСлужебный.ПолучитьНастройкиПользователя(НастройкиПользователя, ИсточникНастроек);
	КонецЕсли;	
	
	Возврат Результат;
	
КонецФункции

// Служебная функция для формирования секрета пользователя в заголовке запроса
// Параметры:
//  НастройкиПользователя 	- см. НастройкиПользователяПоУмолчанию
//  ПарольКлиента 			- Строка - пароль в закрытом виде
//	
// Возвращаемое значение:
//  Строка - содержит строку для авторизации пользователя в сценарии двухфакторной авторизации
//	
Функция ПолучитьПредставлениеСекрета(НастройкиПользователя, ПарольКлиента = "")
	
	Результат 		= "";
	
	ИсходныеДанные 	= ПолучитьДвоичныеДанныеИзСтроки(НастройкиПользователя.Логин 
						+ ":" 
						+ ПарольКлиента, 
						"UTF-8");
	Результат		= "Basic " + ПолучитьBase64СтрокуИзДвоичныхДанных(ИсходныеДанные);
	
	Возврат Результат;
	
КонецФункции

// Общая функция формирования данных о документе загруженном для обработки
//
// Параметры:
//  РезультатВызова - Структура - результат вызова Rest сервиса
//
// Возвращаемое значение:
//  Структура:
//   * ДополнительнаяИнформация	- Структура:
//    ** ШаблонДокумента		- Строка
//    ** ШаблонКонвертации		- Строка
//    ** МаленькийФайл			- Булево
//   * РазмерФайла				- Число
//   * ИмяФайла					- Строка
//   * ТипФайла					- Строка
//   * Хеш						- Строка - значение хеша
//   * АлгоритмХеша				- Строка
//   * Идентификатор			- Строка - идентификатор документа
//   * ВременныйФайл			- Булево
//   * ВремяДоступа				- Дата - время последнее обращения к документу
//   * ВремяЗагрузки			- Дата	- время загрузки на сервер\
//   * ИдентификаторПользователя- Строка - идентификатор пользователя владельца
//
Функция ИнформацияОДокументеОбработки(РезультатВызова)
	
	Результат = Новый Структура;
	
	ДополнительнаяИнформация = Новый Структура;
	ДополнительнаяИнформация.Вставить("ШаблонДокумента", СвойствоСтруктуры(РезультатВызова, "AdditionalInfo.DocumentTemplate", ""));
	ДополнительнаяИнформация.Вставить("МаленькийФайл", СвойствоСтруктуры(РезультатВызова, "AdditionalInfo.SmallFile", Ложь));
	ДополнительнаяИнформация.Вставить("ШаблонКонвертации", СвойствоСтруктуры(РезультатВызова, "AdditionalInfo.SnippetTemplate", ""));
	
	Результат.Вставить("ДополнительнаяИнформация", ДополнительнаяИнформация);
	Результат.Вставить("РазмерФайла", СвойствоСтруктуры(РезультатВызова, "FileSize", 0));
	Результат.Вставить("ИмяФайла", СвойствоСтруктуры(РезультатВызова, "Name", ""));
	Результат.Вставить("ТипФайла", СвойствоСтруктуры(РезультатВызова, "FileType", ""));
	Результат.Вставить("Хеш", СвойствоСтруктуры(РезультатВызова, "Hash", ""));
	Результат.Вставить("АлгоритмХеша", СвойствоСтруктуры(РезультатВызова, "HashAlgorithm", ""));
	Результат.Вставить("Идентификатор", СвойствоСтруктуры(РезультатВызова, "Id", ""));
	Результат.Вставить("ВременныйФайл", СвойствоСтруктуры(РезультатВызова, "IsTemporary", Ложь));
	Результат.Вставить("ВремяДоступа", ДатаUTC(СвойствоСтруктуры(РезультатВызова, "LastAccessTime", 0)));
	Результат.Вставить("ВремяЗагрузки", ДатаUTC(СвойствоСтруктуры(РезультатВызова, "UploadTime", 0)));
	Результат.Вставить("ИдентификаторПользователя", СвойствоСтруктуры(РезультатВызова, "UserId", ""));
	
	Возврат Результат;
	
КонецФункции

// Общая функция формирования данных о конвертации документа.
//
// Параметры:
//  РезультатВызова 		- Структура - результат вызова Rest сервиса
//
// Возвращаемое значение:
//  Структура:
//    * Идентификатор		- Строка - идентификатор документа, который был конвертирован
//    * Статус			- Строка - статус обработки документа
//    * Формат			- Строка - формат конвертации документа
//    * Описание			- Строка - дополнительная информация
//
Функция ИнформацияОКонвертацииДокумента(РезультатВызова)
	
	Результат = Новый Структура;
	Результат.Вставить("Идентификатор", СвойствоСтруктуры(РезультатВызова, "OriginalDocument", ""));
	Результат.Вставить("Статус", СвойствоСтруктуры(РезультатВызова, "ConvertationStatus", ""));
	Результат.Вставить("Формат", СвойствоСтруктуры(РезультатВызова, "ConvertedFormat", ""));
	Результат.Вставить("Описание",СвойствоСтруктуры(РезультатВызова, "ConvertationStatusReason", ""));
	
	Возврат Результат;
	
КонецФункции

// Конвертация даты UTC (число) в обычную дату
// 
// Параметры:
//   ЧислоДаты - Число
// 
// Возвращаемое значение:
//  Дата
//
Функция ДатаUTC(Знач ЧислоДаты, Добавка = 1970)
	
	Результат = СервисКриптографииDSSКлиентСервер.ДатаUTC(ЧислоДаты, Добавка);
	Возврат Результат;
	
КонецФункции

// Функция-обертка для разбора полей сложнопостроенной структуры.
//
// Параметры:
//  ЗначениеСтруктуры	- Структура
//                   	- Соответствие
//                   	- Массив
//  Ключ 				- Строка - содержит полный путь к нужному значению
//  ЗначениеПоУмолчанию - Произвольный
// 
// Возвращаемое значение:
//  - ДвоичныеДанные
//  - Строка
//  - Структура
//  - Произвольный - см. СервисКриптографииDSSКлиентСервер.ПолучитьПолеСтруктуры
//
Функция СвойствоСтруктуры(ЗначениеСтруктуры, Ключ, ЗначениеПоУмолчанию = Неопределено)
	
	Возврат СервисКриптографииDSSКлиентСервер.ПолучитьПолеСтруктуры(ЗначениеСтруктуры, Ключ, ЗначениеПоУмолчанию);
		
КонецФункции	

// Функция-обертка для функции подстановки параметров в строку.
//
// Параметры:
//  ТекущееЗначение 	- Строка.
//  ПараметрСтроки1		- Неопределено
//                 		- Строка
//  ПараметрСтроки2		- Неопределено
//                 		- Строка
//  ПараметрСтроки3		- Неопределено
//                 		- Строка
// 
// Возвращаемое значение:
//  Строка
//
Функция ЗаполнитьПараметрыСтроки(ТекущееЗначение, 
								ПараметрСтроки1 = Неопределено,
								ПараметрСтроки2 = Неопределено,
								ПараметрСтроки3 = Неопределено)
	
	Возврат СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
				ТекущееЗначение,
				ПараметрСтроки1,
				ПараметрСтроки2,
				ПараметрСтроки3);
		
КонецФункции

// Формирует свойства полученного запроса на сертификат, хранящегося на сервере
//
// Параметры:
//  ДанныеЗапросаНаСертификат - Структура - элемент ответа сервера
//
// Возвращаемое значение: 
//  Структура:
//    * Содержание 		- ДвоичныеДанные - содержание запроса на сертификат
//    * Статус 			- Строка - варианты: Отклонен, Обрабатывается, Одобрен, Регистрация
//    * ТипСертификата 	- Строка - тип сертификата 
//    * Идентификатор 	- Строка - идентификатор созданного запроса на сертификат
//
Функция СвойстваЗапросаНаСертификат(ДанныеЗапросаНаСертификат)
	
	ВсеСтатусы		= Новый Соответствие;
	ВсеСтатусы.Вставить("REJECTED", "Отклонен");
	ВсеСтатусы.Вставить("PENDING", "Обрабатывается");
	ВсеСтатусы.Вставить("ACCEPTED", "Одобрен");
	ВсеСтатусы.Вставить("REGISTRATION", "Регистрация");
	
	ТекущийСтатус = ВсеСтатусы[ДанныеЗапросаНаСертификат.Status];
	ТекущийСтатус = ?(ТекущийСтатус = Неопределено, "НеОбрабатывается", ТекущийСтатус);
	
	Результат = Новый Структура();
	Результат.Вставить("Содержание", Base64Значение(ДанныеЗапросаНаСертификат.Base64Request));
	Результат.Вставить("Статус", ТекущийСтатус);
	Результат.Вставить("ТипСертификата", ДанныеЗапросаНаСертификат.CertificateType);
	Результат.Вставить("Идентификатор", ДанныеЗапросаНаСертификат.ID);
	Результат.Вставить("Имя", ДанныеЗапросаНаСертификат.Subject);
	Результат.Вставить("Владелец", ДанныеЗапросаНаСертификат.DistName);
	
	Возврат Результат;
	
КонецФункции

// Формирует структуру для параметров операции. 
//
// Параметры:
//  ПараметрыОперации 	- Неопределено 
//                    	- Структура
//  КлючЗначения		- Строка
//  НовоеЗначение		- Произвольный
//
// Возвращаемое значение:
//  Структура
//
Функция ПроверитьПараметрыОперации(ПараметрыОперации, КлючЗначения = Неопределено, НовоеЗначение = Неопределено)
	
	Если ПараметрыОперации = Неопределено
		ИЛИ ТипЗнч(ПараметрыОперации) <> Тип("Структура") Тогда
		Результат = Новый Структура;
	Иначе
		Результат = ОбщегоНазначения.СкопироватьРекурсивно(ПараметрыОперации);
	КонецЕсли;
	
	Если КлючЗначения <> Неопределено 
		И НЕ Результат.Свойство(КлючЗначения) Тогда
		Результат.Вставить(КлючЗначения, НовоеЗначение);
	КонецЕсли;	
	
	Возврат Результат;
	
КонецФункции

// Формирует значение пароля на основе переданных данных.
//
// Параметры:
//  ОбъектПароля 			- Структура, Строка - см. СервисКриптографииDSSКлиентСервер.ОбъектПароля
//  НастройкиПользователя 	- Структура - структура хранящая данные сессионные данные учетной записи
//  ИсточникНастроек		- Строка
//                  		- Неопределено
//
// Возвращаемое значение:
//  Строка
//
Функция ПолучитьЗначениеПароля(ОбъектПароля, НастройкиПользователя, ИсточникНастроек = Неопределено)
	
	Если ТипЗнч(ОбъектПароля) = Тип("Структура") Тогда
		Если ОбъектПароля.Состояние = 4 
			ИЛИ ОбъектПароля.Состояние = 3 
			ИЛИ ОбъектПароля.Состояние = 2 Тогда
			Результат = "";
			
		ИначеЕсли ОбъектПароля.Состояние = 1 Тогда
			Результат = ОткрытьСекретПользователя(ОбъектПароля.Значение, НастройкиПользователя);
			
		ИначеЕсли ОбъектПароля.Состояние = 5 Тогда
			ВсеДанные = СервисКриптографииDSSСлужебный.ПолучитьКонтейнерНастроек(СервисКриптографииDSSСлужебный.ПолучитьИсточникНастроек(ИсточникНастроек));
			НашлиДанные = ВсеДанные.Параметры[ОбъектПароля.Значение];
			Если НашлиДанные = Неопределено Тогда
				Результат = "";
			Иначе
				Результат = ОткрытьСекретПользователя(НашлиДанные, НастройкиПользователя);
			КонецЕсли;
			
		Иначе	
			Результат = Строка(ОбъектПароля.Значение);
			
		КонецЕсли;
			
	Иначе
		Результат = ОбъектПароля;
		
	КонецЕсли;	
	
	Возврат Результат;
	
КонецФункции

// Специализированная функция расшифровки секрета пользователя (пин-код, пароль), для последующей передачи сервису
//
// Параметры:
//  СекретПользователя 		- Строка - зашифрованное представление пароля
//  НастройкиПользователя 	- Структура - структура хранящая данные сессионные данные учетной записи
//
// Возвращаемое значение:
//  Строка - открытое значение пароля
//	
Функция ОткрытьСекретПользователя(СекретПользователя, НастройкиПользователя)
	
	Результат = "";
	
	ПризнакКонфиденциальности = НастройкиПользователя.ПризнакКонфиденциальности;
	
	Если ЗначениеЗаполнено(СекретПользователя) И ПризнакКонфиденциальности = 0 Тогда
		Результат = СекретПользователя;
		
	ИначеЕсли ЗначениеЗаполнено(СекретПользователя) Тогда
		Случайность	= СтрЗаменить(НастройкиПользователя.АвторизованныйПользователь, "-", "");
		Случайность	= ПолучитьБуферДвоичныхДанныхИзHexСтроки(Случайность);
		КлючПользователя = ПолучитьБуферДвоичныхДанныхИзBase64Строки(СекретПользователя);
		
		Модуль = КлючПользователя.Размер;
		НовыйКлюч = Новый БуферДвоичныхДанных(КлючПользователя.Размер);
		
		Перемешать = Новый Массив(Модуль);
		Для Счетчик = 1 По Модуль Цикл
			Перемешать.Установить(Счетчик - 1, Счетчик);
		КонецЦикла;
		
		Для Счетчик = 1 По Модуль Цикл
			ИндексЭлемента = Счетчик % Случайность.Размер;
			ЗначениеЭлемента = Случайность.Получить(ИндексЭлемента) % Модуль;
			НашлиЗначение = Перемешать.Найти(ЗначениеЭлемента);
			НашлиСчетчик = Перемешать.Найти(Счетчик);
			Если НашлиЗначение <> Неопределено
				И НашлиСчетчик <> Неопределено Тогда
				Перемешать.Установить(НашлиСчетчик, ЗначениеЭлемента);
				Перемешать.Установить(НашлиЗначение, Счетчик);
			КонецЕсли;	
		КонецЦикла;
		
		Начало = Случайность.Получить(8) % Модуль;
		
		Ключ1 = Случайность.Получить(6);
		Ключ2 = Случайность.Получить(7);
		
		Для Счетчик = 1 По Модуль Цикл
			СледующийБайт = КлючПользователя.Получить(Счетчик - 1);
			СледующийБайт = ?(Счетчик % 2 = 1, СледующийБайт - Ключ1, СледующийБайт - Ключ2);
			Если СледующийБайт < 0 Тогда
				СледующийБайт = СледующийБайт + 256;
			КонецЕсли;	
			КлючПользователя.Установить(Счетчик - 1, СледующийБайт);
		КонецЦикла;
		
		Для Счетчик = 1 По Модуль Цикл
			СледующееМесто = Перемешать[Начало];
			СледующийБайт = КлючПользователя.Получить(Счетчик - 1);
			НовыйКлюч.Установить(СледующееМесто - 1, СледующийБайт);
			Начало = (Начало + 1) % Модуль;
		КонецЦикла;
		
		Результат = ПолучитьСтрокуИзБуфераДвоичныхДанных(НовыйКлюч);
		Результат = Сред(Результат, 8);
	КонецЕсли;	
	
	Возврат Результат;
	
КонецФункции

// Служебная функция технического разбора маркера безопасности в формате JWT 
//
// Параметры:
//  СодержимоеТокена 	- Строка - строка в формате Base64
//  ПараметрыОперации 	- Структура, ФиксированнаяСтруктура - позволяет указать дополнительные параметры операции.
//
// Возвращаемое значение:
//  Структура:
//    * Логин			- Строка
//    * Идентификатор	- Строка
//    * Телефон			- Строка
//    * ЭлектроннаяПочта- Строка
//    * ИдентификаторЦИ	- Строка 
//
Функция РазобратьТокенАвторизации(СодержимоеТокена, ПараметрыОперации = Неопределено)
	
	Результат = Новый Структура();
	Результат.Вставить("Логин", "");
	Результат.Вставить("Идентификатор", "");
	Результат.Вставить("Телефон", "");
	Результат.Вставить("ЭлектроннаяПочта", "");
	Результат.Вставить("ИдентификаторЦИ", "");
	
	Попытка
		МассивРазделов		= СтрРазделить(СодержимоеТокена, ".");
		
		ПодготовленныйТекст	= СтрЗаменить(МассивРазделов[1], "-", "+");
		ПодготовленныйТекст	= СтрЗаменить(ПодготовленныйТекст, "_", "/");
		ПодготовленныйТекст	= ПодготовленныйТекст + "==";
		
		ПредставлениеТокена = ПолучитьСтрокуИзДвоичныхДанных(Base64Значение(ПодготовленныйТекст));
		КлючевыеПоля		= ОбщегоНазначения.JSONВЗначение(ПредставлениеТокена);
		Результат.Логин				= КлючевыеПоля["unique_name"];
		Результат.Идентификатор		= КлючевыеПоля["nameid"];
		Результат.Телефон			= КлючевыеПоля["http://schemas.xmlsoap.org/ws/2005/05/identity/claims/mobilephone"];
		Результат.ЭлектроннаяПочта	= КлючевыеПоля["email"];
		Результат.ИдентификаторЦИ	= КлючевыеПоля["dss_iss"];
		
	Исключение
		ОбъектОшибки = ИнформацияОбОшибке();
		СервисКриптографииDSSСлужебный.ПротоколОшибкиПриВызове(
				ОбработкаОшибок.ПодробноеПредставлениеОшибки(ОбъектОшибки), 
				НСтр("ru = 'Разобрать токен авторизации'"), 
				СодержимоеТокена,
				ОбъектОшибки,
				ПараметрыОперации);

	КонецПопытки;
	
	Возврат Результат;
	
КонецФункции

// Универсальная функция для анализа результата асинхронной операции
//
// Параметры:
//  РезультатЗапроса	- Структура
//                  	- Соответствие
// 
// Возвращаемое значение:
//  Структура
//
Функция ОписаниеАсинхроннойОперации(РезультатЗапроса, ИмяКоллекции = "")
	
	ОписаниеОперации = Новый Структура;
	ОписаниеОперации.Вставить("ИдентификаторОперации", "");
	ОписаниеОперации.Вставить("СрокДействия", '00010101');
	ОписаниеОперации.Вставить("ТребуетПодтверждения", Ложь);
	
	Результат = Новый Структура;
	Результат.Вставить("Выполнено", Истина);
	Результат.Вставить("Ошибка", "");
	Результат.Вставить("КодОшибки", "");
	Результат.Вставить("Действия", Неопределено);
	Результат.Вставить("ОписаниеОперации", ОписаниеОперации);
	
	СтатусОперации = РезультатЗапроса.Status;
	СтатусОшибки = СвойствоСтруктуры(РезультатЗапроса, "Error", "");
	
	ОписаниеОперации.ИдентификаторОперации = СвойствоСтруктуры(РезультатЗапроса, "ID", "");
	ОписаниеОперации.СрокДействия = ДатаUTC(СвойствоСтруктуры(РезультатЗапроса, "ExpirationDate", 0));
	
	Если СтатусОперации = "Error" ИЛИ ЗначениеЗаполнено(СтатусОшибки) Тогда
		Результат.Выполнено = Ложь;
		Результат.Ошибка = СвойствоСтруктуры(РезультатЗапроса, "ErrorDescription", "");
	ИначеЕсли СтатусОперации = "Created" Тогда
		ОписаниеОперации.ТребуетПодтверждения = Истина;
	ИначеЕсли ЗначениеЗаполнено(ИмяКоллекции) Тогда
		Результат.Действия = СвойствоСтруктуры(РезультатЗапроса, ИмяКоллекции, Новый Массив);
		Для Каждого СтрокаОтвета Из Результат.Действия Цикл
			Если СтрокаОтвета.Status = "Error" Тогда
				Результат.Выполнено = Ложь;
				Результат.КодОшибки = СтрокаОтвета.Error;
				Результат.Ошибка = Результат.Ошибка + СтрокаОтвета.ErrorDescription;
			КонецЕсли;
		КонецЦикла;	
	КонецЕсли;	
	
	Возврат Результат;
	
КонецФункции

// Проверяет параметр подписи "Сервер штампа времени" на заполнение.
// Если передан пустой параметр, но в настройках пользователя есть информация, то заполняется она.
//
// Параметры:
//  НастройкиПользователя 	- Структура
//  ИмяПараметра 			- Строка
//  ЗначениеПараметра       - Строка
//
// Возвращаемое значение:
//  Строка
//
Функция ПроверитьПараметрПодписи(НастройкиПользователя, ИмяПараметра, ЗначениеПараметра)
	
	Результат = ЗначениеПараметра;
	
	Если ВРег(ИмяПараметра) = ВРег("TSPAddress") 
		И НЕ ЗначениеЗаполнено(ЗначениеПараметра)
		И НастройкиПользователя.Политика.СервераШтамповВремени.Количество() > 0 Тогда
		Результат = НастройкиПользователя.Политика.СервераШтамповВремени[0].Адрес;
	КонецЕсли;
	
	Возврат Результат;
	
КонецФункции

#КонецОбласти